Repository: scrapinghub/portia Branch: master Commit: 606467d278ea Files: 729 Total size: 5.8 MB Directory structure: gitextract_l8nvd49y/ ├── .dockerignore ├── .drone.yml ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── CHANGES ├── Dockerfile ├── LICENSE ├── README.md ├── VERSION ├── Vagrantfile ├── bin/ │ └── bump_version.py ├── docker/ │ ├── compile-assets.sh │ ├── entry │ ├── nginx/ │ │ ├── nginx.conf │ │ ├── proxy_portia_server.conf │ │ └── proxy_slyd.conf │ ├── portia.conf │ ├── provision.sh │ ├── qt_install.qs │ ├── restore-mtime.sh │ └── run-tests.sh ├── docker-compose.yml ├── docs/ │ ├── Makefile │ ├── conf.py │ ├── examples.rst │ ├── faq.rst │ ├── getting-started.rst │ ├── index.rst │ ├── installation.rst │ ├── items.rst │ ├── make.bat │ ├── projects.rst │ ├── samples.rst │ └── spiders.rst ├── portia_server/ │ ├── db_repo/ │ │ ├── __init__.py │ │ ├── apps.py │ │ ├── migrations/ │ │ │ ├── 0001_initial.py │ │ │ ├── __init__.py │ │ │ └── slyd_to_django.sql │ │ ├── models.py │ │ └── repo.py │ ├── manage.py │ ├── portia_api/ │ │ ├── __init__.py │ │ ├── apps.py │ │ ├── errors.py │ │ ├── jsonapi/ │ │ │ ├── __init__.py │ │ │ ├── exceptions.py │ │ │ ├── parsers.py │ │ │ ├── registry.py │ │ │ ├── relationships.py │ │ │ ├── renderers.py │ │ │ ├── response.py │ │ │ ├── serializers.py │ │ │ └── utils.py │ │ ├── resources/ │ │ │ ├── __init__.py │ │ │ ├── annotations.py │ │ │ ├── extractors.py │ │ │ ├── fields.py │ │ │ ├── items.py │ │ │ ├── models.py │ │ │ ├── projects.py │ │ │ ├── response.py │ │ │ ├── route.py │ │ │ ├── samples.py │ │ │ ├── schemas.py │ │ │ ├── serializers.py │ │ │ └── spiders.py │ │ ├── routers.py │ │ ├── tests/ │ │ │ ├── __init__.py │ │ │ └── test_routes.py │ │ ├── urls.py │ │ └── utils/ │ │ ├── __init__.py │ │ ├── annotations.py │ │ ├── copy.py │ │ ├── deploy/ │ │ │ ├── base.py │ │ │ ├── package.py │ │ │ ├── scrapinghub.py │ │ │ └── scrapyd.py │ │ ├── download.py │ │ ├── extract.py │ │ ├── projects.py │ │ └── spiders.py │ ├── portia_orm/ │ │ ├── __init__.py │ │ ├── apps.py │ │ ├── base.py │ │ ├── collection.py │ │ ├── datastore.py │ │ ├── decorators.py │ │ ├── deletion.py │ │ ├── exceptions.py │ │ ├── fields.py │ │ ├── middleware.py │ │ ├── models.py │ │ ├── registry.py │ │ ├── relationships.py │ │ ├── serializers.py │ │ ├── snapshots.py │ │ ├── tests/ │ │ │ ├── __init__.py │ │ │ ├── models.py │ │ │ ├── test_basic.py │ │ │ ├── test_collection.py │ │ │ ├── test_model.py │ │ │ ├── test_relationship.py │ │ │ └── utils.py │ │ ├── utils.py │ │ └── validators.py │ ├── portia_server/ │ │ ├── __init__.py │ │ ├── backends.py │ │ ├── models.py │ │ ├── settings.py │ │ ├── urls.py │ │ ├── views.py │ │ └── wsgi.py │ ├── requirements.txt │ └── storage/ │ ├── __init__.py │ ├── apps.py │ ├── backends.py │ ├── jsondiff.py │ ├── projecttemplates.py │ └── repoman.py ├── portiaui/ │ ├── .bowerrc │ ├── .editorconfig │ ├── .ember-cli │ ├── .gitignore │ ├── .jshintrc │ ├── .watchmanconfig │ ├── app/ │ │ ├── adapters/ │ │ │ ├── application.js │ │ │ └── project.js │ │ ├── app.js │ │ ├── components/ │ │ │ ├── .gitkeep │ │ │ ├── add-start-url-button.js │ │ │ ├── animation-container.js │ │ │ ├── annotation-options.js │ │ │ ├── browser-iframe.js │ │ │ ├── browser-url-blocked.js │ │ │ ├── browser-url-failing.js │ │ │ ├── browser-view-port.js │ │ │ ├── buffered-input.js │ │ │ ├── colored-badge.js │ │ │ ├── colored-span.js │ │ │ ├── combo-box.js │ │ │ ├── create-project-button.js │ │ │ ├── create-spider-button.js │ │ │ ├── data-structure-annotations.js │ │ │ ├── data-structure-listing.js │ │ │ ├── dropdown-delete.js │ │ │ ├── dropdown-divider.js │ │ │ ├── dropdown-header.js │ │ │ ├── dropdown-item.js │ │ │ ├── dropdown-menu.js │ │ │ ├── dropdown-widget.js │ │ │ ├── edit-sample-button.js │ │ │ ├── element-overlay.js │ │ │ ├── element-rect-overlay.js │ │ │ ├── extracted-item-table.js │ │ │ ├── extracted-items-group.js │ │ │ ├── extracted-items-json-panel.js │ │ │ ├── extracted-items-json-value.js │ │ │ ├── extracted-items-json.js │ │ │ ├── extracted-items-panel.js │ │ │ ├── extracted-items-status.js │ │ │ ├── extracted-items-tab.js │ │ │ ├── extractor-options.js │ │ │ ├── feed-url-options.js │ │ │ ├── field-options.js │ │ │ ├── fragment-options.js │ │ │ ├── generated-url-options.js │ │ │ ├── help-icon.js │ │ │ ├── icon-button.js │ │ │ ├── indentation-spacer.js │ │ │ ├── input-with-clear.js │ │ │ ├── inspector-panel.js │ │ │ ├── link-crawling-options.js │ │ │ ├── list-item-add-annotation-menu.js │ │ │ ├── list-item-annotation-field.js │ │ │ ├── list-item-badge.js │ │ │ ├── list-item-combo.js │ │ │ ├── list-item-editable.js │ │ │ ├── list-item-field-type.js │ │ │ ├── list-item-icon-menu.js │ │ │ ├── list-item-icon.js │ │ │ ├── list-item-item-schema.js │ │ │ ├── list-item-link-crawling.js │ │ │ ├── list-item-relation-manager.js │ │ │ ├── list-item-selectable.js │ │ │ ├── list-item-text.js │ │ │ ├── notification-container.js │ │ │ ├── notification-message.js │ │ │ ├── page-actions-editor.js │ │ │ ├── project-list.js │ │ │ ├── project-listing.js │ │ │ ├── project-structure-listing.js │ │ │ ├── project-structure-spider-feed-url.js │ │ │ ├── project-structure-spider-generated-url.js │ │ │ ├── project-structure-spider-url.js │ │ │ ├── regex-pattern-list.js │ │ │ ├── reorder-handler.js │ │ │ ├── save-status.js │ │ │ ├── schema-structure-listing.js │ │ │ ├── scrapinghub-links.js │ │ │ ├── select-box.js │ │ │ ├── show-links-button.js │ │ │ ├── show-links-legend.js │ │ │ ├── sliding-main.js │ │ │ ├── spider-indentation.js │ │ │ ├── spider-message.js │ │ │ ├── spider-options.js │ │ │ ├── spider-row.js │ │ │ ├── spider-structure-listing.js │ │ │ ├── start-url-options.js │ │ │ ├── tool-group.js │ │ │ ├── tool-panel.js │ │ │ ├── tool-tab.js │ │ │ ├── tooltip-container.js │ │ │ ├── tooltip-icon.js │ │ │ ├── tree-list-item-row.js │ │ │ ├── tree-list-item.js │ │ │ ├── tree-list.js │ │ │ └── url-bar.js │ │ ├── controllers/ │ │ │ ├── .gitkeep │ │ │ └── projects/ │ │ │ ├── project/ │ │ │ │ ├── conflicts/ │ │ │ │ │ └── conflict.js │ │ │ │ ├── conflicts.js │ │ │ │ ├── schema/ │ │ │ │ │ └── field/ │ │ │ │ │ └── options.js │ │ │ │ ├── spider/ │ │ │ │ │ ├── link-options.js │ │ │ │ │ ├── options.js │ │ │ │ │ └── sample/ │ │ │ │ │ ├── data/ │ │ │ │ │ │ └── annotation/ │ │ │ │ │ │ └── options.js │ │ │ │ │ └── data.js │ │ │ │ └── spider.js │ │ │ └── project.js │ │ ├── helpers/ │ │ │ ├── .gitkeep │ │ │ ├── array-get.js │ │ │ ├── attribute-annotation.js │ │ │ ├── chain-actions.js │ │ │ ├── guid.js │ │ │ ├── includes.js │ │ │ ├── indexed-object.js │ │ │ ├── is-empty-object.js │ │ │ ├── is-object-or-array.js │ │ │ └── is-object.js │ │ ├── index.html │ │ ├── initializers/ │ │ │ └── ui-state.js │ │ ├── instance-initializers/ │ │ │ └── error-handler.js │ │ ├── mixins/ │ │ │ ├── options-route.js │ │ │ └── save-spider-mixin.js │ │ ├── models/ │ │ │ ├── .gitkeep │ │ │ ├── annotation.js │ │ │ ├── base-annotation.js │ │ │ ├── base.js │ │ │ ├── extractor.js │ │ │ ├── field.js │ │ │ ├── item.js │ │ │ ├── project.js │ │ │ ├── sample.js │ │ │ ├── schema.js │ │ │ ├── spider.js │ │ │ └── start-url.js │ │ ├── resolver.js │ │ ├── router.js │ │ ├── routes/ │ │ │ ├── .gitkeep │ │ │ ├── application.js │ │ │ ├── browsers.js │ │ │ ├── index.js │ │ │ ├── projects/ │ │ │ │ ├── project/ │ │ │ │ │ ├── compatibility.js │ │ │ │ │ ├── conflicts/ │ │ │ │ │ │ └── conflict.js │ │ │ │ │ ├── conflicts.js │ │ │ │ │ ├── schema/ │ │ │ │ │ │ ├── field/ │ │ │ │ │ │ │ └── options.js │ │ │ │ │ │ └── field.js │ │ │ │ │ ├── schema.js │ │ │ │ │ ├── spider/ │ │ │ │ │ │ ├── link-options.js │ │ │ │ │ │ ├── options.js │ │ │ │ │ │ ├── sample/ │ │ │ │ │ │ │ ├── data/ │ │ │ │ │ │ │ │ ├── annotation/ │ │ │ │ │ │ │ │ │ └── options.js │ │ │ │ │ │ │ │ ├── annotation.js │ │ │ │ │ │ │ │ └── item.js │ │ │ │ │ │ │ ├── data.js │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── sample.js │ │ │ │ │ │ ├── start-url/ │ │ │ │ │ │ │ └── options.js │ │ │ │ │ │ └── start-url.js │ │ │ │ │ └── spider.js │ │ │ │ └── project.js │ │ │ └── projects.js │ │ ├── serializers/ │ │ │ └── application.js │ │ ├── services/ │ │ │ ├── annotation-structure.js │ │ │ ├── browser.js │ │ │ ├── capabilities.js │ │ │ ├── changes.js │ │ │ ├── clock.js │ │ │ ├── dispatcher.js │ │ │ ├── extracted-items.js │ │ │ ├── notification-manager.js │ │ │ ├── overlays.js │ │ │ ├── position-monitor.js │ │ │ ├── saving-notification.js │ │ │ ├── selector-matcher.js │ │ │ ├── store.js │ │ │ ├── ui-state.js │ │ │ └── web-socket.js │ │ ├── storages/ │ │ │ ├── cookies.js │ │ │ ├── page-loads.js │ │ │ ├── ui-state-collapsed-panels.js │ │ │ └── ui-state-selected-tools.js │ │ ├── styles/ │ │ │ ├── _animations.scss │ │ │ ├── _bootstrap_overrides.scss │ │ │ ├── _icons.scss │ │ │ ├── _lib_config.scss │ │ │ ├── _variables.scss │ │ │ ├── app.scss │ │ │ ├── components/ │ │ │ │ ├── animation-container.scss │ │ │ │ ├── browser-iframe.scss │ │ │ │ ├── browser-view-port.scss │ │ │ │ ├── combo-box.scss │ │ │ │ ├── conflicts.scss │ │ │ │ ├── dropdown-delete.scss │ │ │ │ ├── dropdown-menu.scss │ │ │ │ ├── dropdown-widget.scss │ │ │ │ ├── extracted-item-table.scss │ │ │ │ ├── extracted-items-json-panel.scss │ │ │ │ ├── extractor-options.scss │ │ │ │ ├── fragment-options.scss │ │ │ │ ├── help-icon.scss │ │ │ │ ├── icon-button.scss │ │ │ │ ├── indentation-spacer.scss │ │ │ │ ├── input-with-clear.scss │ │ │ │ ├── inspector-panel.scss │ │ │ │ ├── list-item-badge.scss │ │ │ │ ├── list-item-combo.scss │ │ │ │ ├── list-item-editable.scss │ │ │ │ ├── list-item-icon.scss │ │ │ │ ├── list-item-selectable.scss │ │ │ │ ├── list-item-text.scss │ │ │ │ ├── notifications.scss │ │ │ │ ├── page-actions.scss │ │ │ │ ├── project-structure-spider-generation-url.scss │ │ │ │ ├── regex-pattern-list.scss │ │ │ │ ├── save-status.scss │ │ │ │ ├── select-box.scss │ │ │ │ ├── show-links-legend.scss │ │ │ │ ├── side-bar.scss │ │ │ │ ├── sliding-main.scss │ │ │ │ ├── start-url-options.scss │ │ │ │ ├── tool-group.scss │ │ │ │ ├── tool-panel.scss │ │ │ │ ├── tooltip-container.scss │ │ │ │ ├── top-bar.scss │ │ │ │ ├── tree-list.scss │ │ │ │ └── url-bar.scss │ │ │ ├── document.scss │ │ │ ├── droplet.scss │ │ │ ├── generic.scss │ │ │ ├── layout/ │ │ │ │ ├── _clickable.scss │ │ │ │ ├── _forms.scss │ │ │ │ └── _full-page-content.scss │ │ │ └── templates/ │ │ │ ├── application.scss │ │ │ ├── browsers.scss │ │ │ └── projects.scss │ │ ├── templates/ │ │ │ ├── application.hbs │ │ │ ├── branding.hbs │ │ │ ├── browsers.hbs │ │ │ ├── components/ │ │ │ │ ├── .gitkeep │ │ │ │ ├── add-start-url-button.hbs │ │ │ │ ├── animation-container.hbs │ │ │ │ ├── annotation-options.hbs │ │ │ │ ├── browser-iframe.hbs │ │ │ │ ├── browser-list.hbs │ │ │ │ ├── browser-url-blocked.hbs │ │ │ │ ├── browser-url-failing.hbs │ │ │ │ ├── browser-view-port.hbs │ │ │ │ ├── buffered-input.hbs │ │ │ │ ├── colored-badge.hbs │ │ │ │ ├── colored-span.hbs │ │ │ │ ├── combo-box.hbs │ │ │ │ ├── create-project-button.hbs │ │ │ │ ├── create-spider-button.hbs │ │ │ │ ├── data-structure-annotations.hbs │ │ │ │ ├── data-structure-listing.hbs │ │ │ │ ├── dropdown-delete.hbs │ │ │ │ ├── dropdown-divider.hbs │ │ │ │ ├── dropdown-header.hbs │ │ │ │ ├── dropdown-item.hbs │ │ │ │ ├── dropdown-menu.hbs │ │ │ │ ├── dropdown-widget.hbs │ │ │ │ ├── edit-sample-button.hbs │ │ │ │ ├── element-overlay.hbs │ │ │ │ ├── element-rect-overlay.hbs │ │ │ │ ├── extracted-item-table.hbs │ │ │ │ ├── extracted-items-group.hbs │ │ │ │ ├── extracted-items-json-panel.hbs │ │ │ │ ├── extracted-items-json-value.hbs │ │ │ │ ├── extracted-items-json.hbs │ │ │ │ ├── extracted-items-panel.hbs │ │ │ │ ├── extracted-items-status.hbs │ │ │ │ ├── extracted-items-tab.hbs │ │ │ │ ├── extractor-options.hbs │ │ │ │ ├── feed-url-options.hbs │ │ │ │ ├── field-options.hbs │ │ │ │ ├── fragment-options.hbs │ │ │ │ ├── generated-url-options.hbs │ │ │ │ ├── help-icon.hbs │ │ │ │ ├── icon-button.hbs │ │ │ │ ├── input-with-clear.hbs │ │ │ │ ├── inspector-panel.hbs │ │ │ │ ├── json-file-compare.hbs │ │ │ │ ├── link-crawling-options.hbs │ │ │ │ ├── list-item-add-annotation-menu.hbs │ │ │ │ ├── list-item-annotation-field.hbs │ │ │ │ ├── list-item-badge.hbs │ │ │ │ ├── list-item-combo.hbs │ │ │ │ ├── list-item-editable.hbs │ │ │ │ ├── list-item-field-type.hbs │ │ │ │ ├── list-item-icon-menu.hbs │ │ │ │ ├── list-item-icon.hbs │ │ │ │ ├── list-item-item-schema.hbs │ │ │ │ ├── list-item-link-crawling.hbs │ │ │ │ ├── list-item-relation-manager.hbs │ │ │ │ ├── list-item-selectable.hbs │ │ │ │ ├── list-item-text.hbs │ │ │ │ ├── notification-container.hbs │ │ │ │ ├── notification-message.hbs │ │ │ │ ├── page-actions-editor.hbs │ │ │ │ ├── project-list.hbs │ │ │ │ ├── project-listing.hbs │ │ │ │ ├── project-structure-listing.hbs │ │ │ │ ├── project-structure-spider-feed-url.hbs │ │ │ │ ├── project-structure-spider-generated-url.hbs │ │ │ │ ├── project-structure-spider-url.hbs │ │ │ │ ├── regex-pattern-list.hbs │ │ │ │ ├── save-status.hbs │ │ │ │ ├── schema-structure-listing.hbs │ │ │ │ ├── scrapinghub-links.hbs │ │ │ │ ├── select-box.hbs │ │ │ │ ├── show-links-button.hbs │ │ │ │ ├── show-links-legend.hbs │ │ │ │ ├── sliding-main.hbs │ │ │ │ ├── spider-indentation.hbs │ │ │ │ ├── spider-message.hbs │ │ │ │ ├── spider-options.hbs │ │ │ │ ├── spider-row.hbs │ │ │ │ ├── spider-structure-listing.hbs │ │ │ │ ├── start-url-options.hbs │ │ │ │ ├── tool-group.hbs │ │ │ │ ├── tool-panel.hbs │ │ │ │ ├── tool-tab.hbs │ │ │ │ ├── tooltip-container.hbs │ │ │ │ ├── tooltip-icon.hbs │ │ │ │ ├── tree-list-item-row.hbs │ │ │ │ ├── tree-list-item.hbs │ │ │ │ ├── tree-list.hbs │ │ │ │ └── url-bar.hbs │ │ │ ├── options-panels.hbs │ │ │ ├── projects/ │ │ │ │ ├── project/ │ │ │ │ │ ├── conflicts/ │ │ │ │ │ │ ├── file-selector.hbs │ │ │ │ │ │ ├── help.hbs │ │ │ │ │ │ ├── resolver.hbs │ │ │ │ │ │ └── topbar.hbs │ │ │ │ │ ├── schema/ │ │ │ │ │ │ ├── field/ │ │ │ │ │ │ │ └── options.hbs │ │ │ │ │ │ ├── field.hbs │ │ │ │ │ │ └── structure.hbs │ │ │ │ │ ├── schema.hbs │ │ │ │ │ ├── spider/ │ │ │ │ │ │ ├── link-options.hbs │ │ │ │ │ │ ├── options.hbs │ │ │ │ │ │ ├── overlays.hbs │ │ │ │ │ │ ├── sample/ │ │ │ │ │ │ │ ├── annotation/ │ │ │ │ │ │ │ │ └── selection.hbs │ │ │ │ │ │ │ ├── data/ │ │ │ │ │ │ │ │ ├── annotation/ │ │ │ │ │ │ │ │ │ └── options.hbs │ │ │ │ │ │ │ │ ├── annotation.hbs │ │ │ │ │ │ │ │ ├── item.hbs │ │ │ │ │ │ │ │ ├── overlays.hbs │ │ │ │ │ │ │ │ ├── structure.hbs │ │ │ │ │ │ │ │ ├── toolbar.hbs │ │ │ │ │ │ │ │ └── tools.hbs │ │ │ │ │ │ │ ├── data.hbs │ │ │ │ │ │ │ ├── item.hbs │ │ │ │ │ │ │ ├── structure.hbs │ │ │ │ │ │ │ └── toolbar.hbs │ │ │ │ │ │ ├── sample.hbs │ │ │ │ │ │ ├── start-url/ │ │ │ │ │ │ │ └── options.hbs │ │ │ │ │ │ ├── structure.hbs │ │ │ │ │ │ ├── toolbar.hbs │ │ │ │ │ │ └── tools.hbs │ │ │ │ │ ├── spider.hbs │ │ │ │ │ ├── structure.hbs │ │ │ │ │ └── toolbar.hbs │ │ │ │ └── project.hbs │ │ │ ├── projects.hbs │ │ │ └── tool-panels.hbs │ │ ├── transforms/ │ │ │ ├── array.js │ │ │ ├── json.js │ │ │ └── start-url.js │ │ ├── utils/ │ │ │ ├── attrs.js │ │ │ ├── browser-features.js │ │ │ ├── colors.js │ │ │ ├── computed.js │ │ │ ├── ensure-promise.js │ │ │ ├── interaction-event.js │ │ │ ├── promises.js │ │ │ ├── selectors.js │ │ │ ├── start-urls.js │ │ │ ├── tree-mirror-delegate.js │ │ │ ├── types.js │ │ │ └── utils.js │ │ ├── validations/ │ │ │ ├── fixed-fragment.js │ │ │ ├── list-fragment.js │ │ │ └── range-fragment.js │ │ └── validators/ │ │ ├── range.js │ │ └── whitespace.js │ ├── bower.json │ ├── config/ │ │ ├── deprecation-workflow.js │ │ ├── environment-development.js │ │ ├── environment-production.js │ │ ├── environment-test.js │ │ └── environment.js │ ├── ember-cli-build.js │ ├── package.json │ ├── public/ │ │ ├── crossdomain.xml │ │ ├── empty-frame.html │ │ ├── frames-not-supported.html │ │ └── robots.txt │ ├── testem.js │ ├── tests/ │ │ ├── .jshintrc │ │ ├── helpers/ │ │ │ ├── destroy-app.js │ │ │ ├── module-for-acceptance.js │ │ │ ├── resolver.js │ │ │ └── start-app.js │ │ ├── index.html │ │ ├── test-helper.js │ │ └── unit/ │ │ ├── .gitkeep │ │ ├── models/ │ │ │ └── start-url-test.js │ │ ├── utils/ │ │ │ ├── selectors-test.js │ │ │ └── start-urls-test.js │ │ └── validators/ │ │ ├── range-test.js │ │ └── whitespace-test.js │ └── vendor/ │ ├── .gitkeep │ ├── modernizr.js │ ├── mutation-summary.js │ └── tree-mirror.js ├── slybot/ │ ├── .gitignore │ ├── CHANGES │ ├── MANIFEST.in │ ├── Makefile.buildbot │ ├── README.rst │ ├── bin/ │ │ ├── makedeb │ │ ├── portiacrawl │ │ └── slybot │ ├── debian/ │ │ ├── changelog │ │ ├── compat │ │ ├── control │ │ ├── copyright │ │ ├── pyversions │ │ └── rules │ ├── docs/ │ │ ├── Makefile │ │ ├── conf.py │ │ ├── index.rst │ │ ├── make.bat │ │ ├── project.rst │ │ └── spiderlets.rst │ ├── requirements-clustering.txt │ ├── requirements-test.txt │ ├── requirements.txt │ ├── scrapy.cfg │ ├── setup.py │ ├── slybot/ │ │ ├── __init__.py │ │ ├── baseurl.py │ │ ├── closespider.py │ │ ├── clustering.py │ │ ├── dupefilter.py │ │ ├── exporter.py │ │ ├── extractors.py │ │ ├── fieldtypes/ │ │ │ ├── __init__.py │ │ │ ├── date.py │ │ │ ├── images.py │ │ │ ├── number.py │ │ │ ├── point.py │ │ │ ├── price.py │ │ │ ├── text.py │ │ │ └── url.py │ │ ├── generic_form.py │ │ ├── item.py │ │ ├── linkextractor/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── ecsv.py │ │ │ ├── html.py │ │ │ ├── pagination.py │ │ │ ├── regex.py │ │ │ └── xml.py │ │ ├── meta.py │ │ ├── pageactions.py │ │ ├── plugins/ │ │ │ ├── __init__.py │ │ │ ├── scrapely_annotations/ │ │ │ │ ├── __init__.py │ │ │ │ ├── annotations.py │ │ │ │ ├── builder.py │ │ │ │ ├── exceptions.py │ │ │ │ ├── extraction/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── container_extractors.py │ │ │ │ │ ├── extractors.py │ │ │ │ │ ├── pageparsing.py │ │ │ │ │ ├── region_extractors.py │ │ │ │ │ └── utils.py │ │ │ │ ├── migration.py │ │ │ │ ├── processors.py │ │ │ │ └── utils.py │ │ │ └── selectors/ │ │ │ └── __init__.py │ │ ├── settings.py │ │ ├── spider.py │ │ ├── spiderlets.py │ │ ├── spidermanager.py │ │ ├── splash.py │ │ ├── starturls/ │ │ │ ├── __init__.py │ │ │ ├── feed_generator.py │ │ │ ├── fragment_generator.py │ │ │ ├── generated_url.py │ │ │ └── generator.py │ │ ├── tests/ │ │ │ ├── __init__.py │ │ │ ├── data/ │ │ │ │ ├── SampleProject/ │ │ │ │ │ ├── extractors.json │ │ │ │ │ ├── items.json │ │ │ │ │ ├── project.json │ │ │ │ │ └── spiders/ │ │ │ │ │ ├── allowed_domains.json │ │ │ │ │ ├── any_allowed_domains.json │ │ │ │ │ ├── books.toscrape.com/ │ │ │ │ │ │ ├── 3617-44af-a2f0/ │ │ │ │ │ │ │ └── original_body.html │ │ │ │ │ │ ├── 3617-44af-a2f0.json │ │ │ │ │ │ ├── 3652-4fa1-a912.json │ │ │ │ │ │ ├── 4583-41b4-9edb/ │ │ │ │ │ │ │ └── original_body.html │ │ │ │ │ │ └── 4583-41b4-9edb.json │ │ │ │ │ ├── books.toscrape.com.json │ │ │ │ │ ├── books.toscrape.com_1.json │ │ │ │ │ ├── cargurus.json │ │ │ │ │ ├── ebay.json │ │ │ │ │ ├── ebay2.json │ │ │ │ │ ├── ebay3.json │ │ │ │ │ ├── ebay4.json │ │ │ │ │ ├── example.com.json │ │ │ │ │ ├── example2.com.json │ │ │ │ │ ├── example3.com.json │ │ │ │ │ ├── example4.com.json │ │ │ │ │ ├── networkhealth.com/ │ │ │ │ │ │ ├── networkhealthtemplate/ │ │ │ │ │ │ │ ├── annotated_body.html │ │ │ │ │ │ │ └── original_body.html │ │ │ │ │ │ └── networkhealthtemplate.json │ │ │ │ │ ├── networkhealth.com.json │ │ │ │ │ ├── pinterest.com.json │ │ │ │ │ ├── seedsofchange.com.json │ │ │ │ │ ├── seedsofchange.json │ │ │ │ │ ├── seedsofchange2.json │ │ │ │ │ └── sitemaps.json │ │ │ │ ├── atom_sample.xml │ │ │ │ ├── ebay_advanced_search.html │ │ │ │ ├── pinterest.html │ │ │ │ ├── rss_sample.xml │ │ │ │ ├── sitemap_sample.xml │ │ │ │ ├── templates/ │ │ │ │ │ ├── 411_list.json │ │ │ │ │ ├── autoevolution.html │ │ │ │ │ ├── autoevolution.json │ │ │ │ │ ├── autoevolution2.json │ │ │ │ │ ├── cars.com.json │ │ │ │ │ ├── cars.com_nested.json │ │ │ │ │ ├── cs-cart.json │ │ │ │ │ ├── daft_ie.html │ │ │ │ │ ├── daft_list.json │ │ │ │ │ ├── firmen.wko.at.html │ │ │ │ │ ├── firmen.wko.at.json │ │ │ │ │ ├── hn.html │ │ │ │ │ ├── patchofland.html │ │ │ │ │ ├── so_annotations.json │ │ │ │ │ ├── stack_overflow.html │ │ │ │ │ ├── stips.co.il.html │ │ │ │ │ ├── stips.co.il.json │ │ │ │ │ └── xceed.json │ │ │ │ └── test_params.txt │ │ │ ├── test_baseurl.py │ │ │ ├── test_dropmeta.py │ │ │ ├── test_dupefilter.py │ │ │ ├── test_extraction_speed.py │ │ │ ├── test_extractors.py │ │ │ ├── test_fieldtypes.py │ │ │ ├── test_fragment_generator.py │ │ │ ├── test_generic_form.py │ │ │ ├── test_linkextractors.py │ │ │ ├── test_migration.py │ │ │ ├── test_multiple_item_extraction.py │ │ │ ├── test_page_actions.py │ │ │ ├── test_schema_validation.py │ │ │ ├── test_selectors.py │ │ │ ├── test_spider.py │ │ │ ├── test_starturls.py │ │ │ ├── test_starturls_generator.py │ │ │ └── utils.py │ │ ├── utils.py │ │ └── validation/ │ │ ├── __init__.py │ │ ├── schema.py │ │ └── schemas.json │ └── tox.ini ├── slyd/ │ ├── .gitignore │ ├── .jshintrc │ ├── README.md │ ├── bin/ │ │ ├── init_mysql_db │ │ ├── sh2sly │ │ └── slyd │ ├── requirements.txt │ ├── setup.py │ ├── slyd/ │ │ ├── __init__.py │ │ ├── authmanager.py │ │ ├── dummyauth.py │ │ ├── errors.py │ │ ├── gitstorage/ │ │ │ ├── __init__.py │ │ │ ├── jsondiff.py │ │ │ ├── projects.py │ │ │ └── projectspec.py │ │ ├── html_utils.py │ │ ├── projects.py │ │ ├── projectspec.py │ │ ├── resource.py │ │ ├── server.py │ │ ├── settings/ │ │ │ ├── __init__.py │ │ │ └── base.py │ │ ├── specmanager.py │ │ ├── splash/ │ │ │ ├── __init__.py │ │ │ ├── commands.py │ │ │ ├── cookies.py │ │ │ ├── css_utils.py │ │ │ ├── ferry.py │ │ │ ├── proxy.py │ │ │ ├── qtutils.py │ │ │ └── utils.py │ │ └── tap.py │ └── twisted/ │ └── plugins/ │ └── slyd_plugin.py └── splash_utils/ ├── compile_slybot.sh ├── filters/ │ └── easylist.txt ├── perform_actions.js ├── waitAsync.js └── z_inject_this.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dockerignore ================================================ .git .vagrant docs */node_modules */bower_components */tests */tmp */db.sqlite3 */.tox */.pyc */__pycache__ ================================================ FILE: .drone.yml ================================================ image: scrapinghub script: - echo "Portia is at:"`git show -s --pretty=%d HEAD` - git restore-mtime - shopt -s extglob - nvm install 10.16.0 - nvm use 10.16.0 - sudo mkdir -p ~/.npm ~/.node-gyp ~/.cache - sudo chown -R ubuntu ~/.npm ~/.node-gyp ~/.cache - npm install -g bower ember-cli@2.6.3 --cache-min 999999 - docker/compile-assets.sh - build_docker_image - publish_to_dockerhub cache: - /home/ubuntu/.npm - /home/ubuntu/.node-gyp - /home/ubuntu/.cache ================================================ FILE: .editorconfig ================================================ # EditorConfig helps developers define and maintain consistent # coding styles between different editors and IDEs # editorconfig.org root = true [*] end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true indent_style = space indent_size = 2 [*.js] indent_style = space indent_size = 2 [*.hbs] indent_style = space indent_size = 2 [*.css] indent_style = space indent_size = 2 [*.html] indent_style = space indent_size = 2 [*.{diff,md}] trim_trailing_whitespace = false ================================================ FILE: .gitattributes ================================================ *.sh eol=lf *.bat eol=crlf *.js text *.py text *.css text *.hbs text *.json text *.html text *.xml text *.yml text *.txt text *.rst text *.md text *.cfg text *.conf text Makefile* text *.png binary *.swf binary *.ttf binary *.woff binary *.woff2 binary ================================================ FILE: .gitignore ================================================ # Python compiled files *__pycache__/* *.pyc # Vagrant files .vagrant/ /.idea/ # Python build files *.egg-info slybot/dist slybot/build slyd/slyd/dist slyd/slyd/build # npm files node_modules/* slyd/bower_components/* slyd/tmp/* npm-debug.log slybot/slybot/splash-script-combined.js # Local Settings slyd/slyd/local_settings.py slybot/slybot/local_slybot_settings.py # Testing slybot/.tox # Docs build directory docs/_build # Development Databases *.sqlite* # Default Portia data directory slyd/slyd/data /data/ ================================================ FILE: .jshintrc ================================================ { "predef": [ "document", "window", "-Promise" ], "browser": true, "boss": true, "curly": true, "debug": false, "devel": true, "eqeqeq": true, "evil": true, "forin": false, "immed": false, "laxbreak": false, "newcap": true, "noarg": true, "noempty": false, "nonew": false, "nomen": false, "onevar": false, "plusplus": false, "regexp": false, "undef": true, "sub": true, "strict": false, "white": false, "eqnull": true, "esnext": true, "unused": true } ================================================ FILE: .travis.yml ================================================ language: python python: 3.7 dist: bionic services: - docker env: - WHEELHOUSE=$HOME/.cache/wheelhouse PIP_FIND_LINKS=file://$WHEELHOUSE PIP_WHEEL_DIR=$WHEELHOUSE cache: directories: - "$HOME/.cache/pip" - "$HOME/.cache/wheelhouse" - portiaui/node_modules - portiaui/bower_components before_install: - docker build -t scrapinghub/portia . - docker ps -a install: - docker run scrapinghub/portia /app/docker/run-tests.sh - pushd portiaui - nvm install 10.16.0 - nvm use 10.16.0 - npm install -g bower ember-cli@2.6.3 - npm install - bower install - popd script: - pushd portiaui - npm rebuild node-sass - npm test - popd before_deploy: - cd slybot - pip install twine - sudo chown -R $USER . deploy: provider: pypi distributions: sdist bdist_wheel user: scrapinghub password: secure: S5hZT2YBncUSkPTyR5RUQnACfTsW2ZtpHeQucIamKWN+xkE8KK9O0cWUMuKQ0q3U5ShFkZdhO4PnBjvtP54Dq9IogJAudkDJCylctf4qGoIlWu01mAoJzcUfrS5KW+VolF/opBJObwG38EIOOsVy9UYq7DeQcryAAG1RuMjONAk= on: all_branches: true tags: true repo: scrapinghub/portia condition: "$TRAVIS_TAG =~ ^slybot-[0-9][.][0-9]*" ================================================ FILE: CHANGES ================================================ 2.0.8 - 2017-04-20 Limit project and spider id length to avoid causing issues in windows Only use auto annotations when calculating container selectors Update portia2code to 0.0.12 - Handle malformed schemas Convert splash url to unicode instead of bytes Enable item nesting in samples from ember config Add logic for keeping track of, and blocking pages that fail to load in Portia Fix 404 error when downloading projects from git backend as a new user 2.0.7 - 2017-03-28 Pin ember data to 2.11.x Do not initialize tree mirror in web page until after initial page load Change order of compilation for injected JS files in splash Set text content correctly for html elements with a content attribute 2.0.6 - 2017-03-07 Add option to have default data format for project Do not show any version control info if it is not enabled Fix Extractor overflow bug Fix error when loading broken samples in UI Fix splash browser tab storing wrong html Fix bug with repr for tab 2.0.5 - 2017-02-27 Add data directory for storing spider data and ignore all new data in it Update install instructions and scripts Update Docs Throw KeyError when trying to get non existent model from collection Fix loading html as raw from the tab in the socket for extraction Fix missing objects in branch by deleting the branch Fix UnicodeDecodeError for downloads and css parsing Fix bytes/unicode issue with slybot extractors 2.0.4 - 2017-02-23 Fix error when trying to load assets by proxy from an invalid tab Fix value resolved to `None` when merging lists Fix unicode error in regex for removing XSS from CSS assets Fix sample loading for old spiders Fix for running legacy spiders Fix storage being cleared by another message while in use Fix error caused by downloading invalid project name Disable error logging for missing websocket command, just log debug message Cache selector searches for container to increase sample build speed Do not throw error for missing annotation data in sample when finding schema Do not log model error when operating on deleted model 2.0.3 - 2017-02-21 Add download option for downloading a Portia project for use with slybot Add download option for downloading a Portia project as Python code Add copy for moving spiders from one project to another Add loading slider when changing page or loading models Add droplet to inform use that they have changes Add better message when websocket is reconnecting Add help icon describing what crawl rules do Add message informing user when they have an unused required field in their schema Add automatic selection of new field type in some cases Add dropdown for projects - publish, discard, download Add option to create new projects from UI (open source only) Add dropdown for spiders - Copy, Download and delete Add dropdown for schemas - delete Fix bug with using master when scheduling spider Fix error when errors with numeric ids are returned by server Fix spider listing loading in UI Fix so that project changes show up whenever there is a change Fix model not being loaded when changing field or schema Fix handling malformed extractor objects Fix merging html data during a conflict - take mine Fix when changing item schema in UI Fix extractors were not shown in UI Fix spiders would not run after a rename Fix deletes where file may be requested for delete more than once Fix with missing node when mirroring page from server Fix incorrect node data when mirroring page from server Fix loading extractors during migration Fix RuntimeError when loading tab url after tab has been closed Fix deletion of html files during cascade delete Fix loading extractors when reading annotations Fix loading html into sample in websocket for extraction Fix logged error due to missing `save_html` callback Fix html not being saved while creating sample Fix loading samples from `template_names` field instead of spider directory 2.0.2 - 2017-01-20 Gracefully handle missing objects in DB 2.0.1 - 2017-01-19 Limit number of spiders shown at once in UI to 15 Fix scheduling when spider has been run from Portia Display helpful error messages to users Replace guid spider ids with spider name Add spider id if it is missing Add a schema for newly created items Fix PathResolutionError for unmigrated samples Better migrate samples that extract from tables 2.0.0 - 2017-01-02 Change backend to use Django instead of Twisted web Created a new JSON API and ORM to handle all Portia objects for greater consistency + efficiency Automatically detect if a user should enable or disable JS for better extraction Added support for generating urls Added support for using a feed as a start url Added support for extracting multiple values to a single field Added support for a spinner showing the extraction progress for a better UX Many bug fixes and stability improvements 16.07.2 - 2016-07-26 Fix bug with `project_filename` method missing Fix bug when initializing project 16.05.1 - 2016-05-17 New transactional request handling Inline element overlays (correctly show tags that may wrap around the page) New download endpoint for projects/spiders `GET portia/api/projects//download[/]` Save selection_mode, pre_text and post_text for annotations Add toggle CSS button 16.04.1 - 2016-04-05 Add link to docs Add auto pagination, learns from start_urls Add git status endpoint for projects Load page when it is specified as url param `url` Save selection mode for annotation when using xpath/css selector Improve Portia on smaller screens Notify users of unpublished changes Reject annotations with elements that share a container with the hovered element Fix issue with extracting items with more than one sibling Fix bug where clicking on help icon toggled checkbox 16.02.2 - 2016-02-16 Fix incompatability with latest splash Fix error with next page link following Log traceback if error occurs in websocket 16.02.1 - 2016-02-09 Add automatic next page link extractor to slybot Show errors to user instead of event id Fix bug where items are not initialized correctly Log websocket errors Fix regex validation Fix conflicts resolution errors 16.01.1 - 2016-01-25 Fix Unicode error when creating spiders Fix install packages Extract data from a list of urls `POST portia/projects//spec/extract/ {"urls": ["http://example.com"]}` Allow `.` to be used in spider and sample names Correctly handle Atom, RSS and XML sitemaps Automatically dismiss suggested annotations if user doesn't use them Correctly place annotations when page contains `` tags Use Qt5 for internal splash instance Fix scrolling page action Fix URL validation 15.12.2 - 2015-12-30 Fix issue when copying spiders that reference deleted extractors Fix issue with using srcdoc in IE Enable annotation suggestions and page actions by default 15.12.1 - 2015-12-03 Fix issue with overwritten JSON library in splash Fix error when merging samples modified in one or more branches Fix event passing in Safari ================================================ FILE: Dockerfile ================================================ FROM ubuntu:16.04 WORKDIR /app/slyd ENV PATH="/opt/qt59/5.9.1/gcc_64/bin:${PATH}" ENV DEBIAN_FRONTEND noninteractive ENV QT_MIRROR http://ftp.fau.de/qtproject/official_releases/qt/5.9/5.9.1/qt-opensource-linux-x64-5.9.1.run COPY docker/portia.conf /app/portia.conf COPY docker/qt_install.qs /app/script.qs COPY docker/provision.sh /app/provision.sh COPY slybot/requirements.txt /app/slybot/requirements.txt COPY slyd/requirements.txt /app/slyd/requirements.txt COPY portia_server/requirements.txt /app/portia_server/requirements.txt RUN /app/provision.sh prepare_install && \ /app/provision.sh install_deps && \ /app/provision.sh install_qtwebkit_deps && \ /app/provision.sh download_official_qt && \ /app/provision.sh install_official_qt && \ /app/provision.sh install_qtwebkit && \ /app/provision.sh install_pyqt5 && \ /app/provision.sh install_python_deps && \ /app/provision.sh install_flash && \ /app/provision.sh install_msfonts && \ /app/provision.sh install_extra_fonts && \ /app/provision.sh remove_builddeps && \ /app/provision.sh remove_extra ADD docker/nginx /etc/nginx ADD . /app RUN pip install -e /app/slyd && \ pip install -e /app/slybot RUN python3 /app/portia_server/manage.py migrate EXPOSE 9001 ENTRYPOINT ["/app/docker/entry"] ================================================ FILE: LICENSE ================================================ Copyright (c) Scrapinghub. 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, 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 documentation and/or other materials provided with the distribution. 3. Neither the name of Portia nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ Portia ====== Portia is a tool that allows you to visually scrape websites without any programming knowledge required. With Portia you can annotate a web page to identify the data you wish to extract, and Portia will understand based on these annotations how to scrape data from similar pages. # Running Portia The easiest way to run Portia is using [Docker]: You can run Portia using Docker & official Portia-image by running: docker run -v ~/portia_projects:/app/data/projects:rw -p 9001:9001 scrapinghub/portia You can also set up a local instance with [Docker-compose] by cloning this repo & running from the root of the folder: docker-compose up For more detailed instructions, and alternatives to using Docker, see the [Installation] docs. # Documentation Documentation can be found from [Read the docs]. Source files can be found in the ``docs`` directory. [Docker]: https://www.docker.com/ [Docker-compose]:https://docs.docker.com/compose [Installation]: http://portia.readthedocs.org/en/latest/installation.html [Read the docs]: http://portia.readthedocs.org/en/latest/index.html [Scrapinghub]: https://portia.scrapinghub.com/ ================================================ FILE: VERSION ================================================ 2.0.8 ================================================ FILE: Vagrantfile ================================================ # vim:ft=ruby Vagrant.configure("2") do |config| config.vm.box = "ubuntu/trusty64" config.vm.host_name = "portia" config.vm.provision :shell, :path => 'docker/provision.sh', :args => [ "install_deps", "install_splash", "install_python_deps", "configure_nginx", "configure_initctl", "migrate_django_db", "start_portia" ] config.vm.network "private_network", ip: "33.33.33.10" config.vm.network "forwarded_port", guest: 9001, host: 9001 config.vm.provider "virtualbox" do |v| v.memory = 2048 v.cpus = 2 end end ================================================ FILE: bin/bump_version.py ================================================ #!/usr/bin/env python3 import os from datetime import datetime _BASE_PATH = os.path.abspath(os.path.dirname(__file__)) VERSION_FILE = os.path.abspath(os.path.join(_BASE_PATH, '../VERSION')) def next_version(version_file): now = datetime.now() this_month = datetime(now.year, now.month, 1) with open(version_file, 'r') as f: version = f.read().strip().split('.') release_month = datetime.strptime('.'.join(version[:-1]), '%y.%m') release_number = int(version[-1]) + 1 if this_month != release_month: release_number = 1 release_number = max(1, release_number) return '{:%y.%m}.{}'.format(this_month, release_number).decode('utf-8') def bump_version_file(filename=None): if filename is None: filename = VERSION_FILE next_version_string = next_version(filename) with open(filename, 'w') as f: f.write(next_version_string) if __name__ == '__main__': bump_version_file() ================================================ FILE: docker/compile-assets.sh ================================================ #!/bin/bash cd portiaui npm install npm run build ================================================ FILE: docker/entry ================================================ #!/bin/bash set -x action=$1 shift _run() { service nginx start _set_env echo $PYTHONPATH /app/slyd/bin/slyd -p 9002 -r /app/portiaui/dist & /app/portia_server/manage.py runserver } _set_env() { path='/app/portia_server:/app/slyd:/app/slybot' export PYTHONPATH="$path" } if [ -z "$action" ]; then _run else case $action in start-dev|start-prod) _run ;; start-webshell) _run_webshell "$@" ;; *) exec $action "$@" ;; esac fi ================================================ FILE: docker/nginx/nginx.conf ================================================ worker_processes 1; events { worker_connections 1024; } http { include mime.types; sendfile on; client_max_body_size 0; gzip on; gzip_static on; gzip_http_version 1.0; gzip_proxied any; gzip_min_length 500; gzip_disable "MSIE [1-6]\."; gzip_types text/plain text/xml text/css text/comma-separated-values text/javascript application/json application/javascript application/x-javascript application/atom+xml; # Configuration for the server server { # Running port listen 9001; root /app/portiaui/dist; location ~ \.map$ { return 404; } location = /index.html { rewrite /index.html /; } location /static { alias /app/portiaui/dist; } location / { try_files $uri @backend; } location /api { include proxy_portia_server.conf; } location /server_capabilities { include proxy_portia_server.conf; } location @backend { include proxy_slyd.conf; } location /ws { proxy_http_version 1.1; proxy_buffering off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; # proxy_set_header Host 127.0.0.1:9002; include proxy_slyd.conf; } } } ================================================ FILE: docker/nginx/proxy_portia_server.conf ================================================ proxy_pass http://127.0.0.1:8000; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; ================================================ FILE: docker/nginx/proxy_slyd.conf ================================================ proxy_pass http://127.0.0.1:9002; proxy_redirect off; proxy_set_header Host $host:9002; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; ================================================ FILE: docker/portia.conf ================================================ description "portia server" start on vagrant-mounted or filesystem stop on runlevel [!2345] script export PYTHONPATH='/vagrant/portia_server:/vagrant/slyd:/vagrant/slybot' /vagrant/slyd/bin/slyd -p 9002 -r /vagrant/portiaui/dist & /vagrant/portia_server/manage.py runserver end script respawn ================================================ FILE: docker/provision.sh ================================================ #!/bin/bash set -e if [ "x$APP_ROOT" = x ] then for dir in "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" /app /vagrant $(pwd) do if [ -d "$dir" ] && [ -d "$dir/slyd" ] then APP_ROOT="$dir" break fi done fi if [ "x$APP_ROOT" = x ] then echo "Could not determine app directory" exit 1 fi echo "APP_ROOT=$APP_ROOT" usage() { cat < /etc/apt/sources.list.d/nginx.list apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ABF5BD827BD9BF62 wget -O - https://deb.nodesource.com/setup_8.x | bash - # Install system dependencies for Qt, Python packages, etc. # ppa:pi-rho/security is a repo for libre2-dev add-apt-repository -y ppa:pi-rho/security && \ apt-get update -q && \ apt-get install -y --no-install-recommends \ python3 \ python3-dev \ python3-pip \ build-essential \ libre2-dev \ liblua5.2-dev \ libsqlite3-dev \ zlib1g \ zlib1g-dev \ netbase \ ca-certificates \ pkg-config \ nodejs \ libmysqlclient-dev \ python-mysql.connector \ python-numpy \ python-openssl \ python-pip \ nginx } install_qtwebkit_deps () { apt-get install -y --no-install-recommends \ xvfb \ libjpeg-turbo8-dev \ libgl1-mesa-dev \ libglu1-mesa-dev \ mesa-common-dev \ libfontconfig1-dev \ libicu-dev \ libpng12-dev \ libxslt1-dev \ libxml2-dev \ libhyphen-dev \ libgbm1 \ libxcb-image0 \ libxcb-icccm4 \ libxcb-keysyms1 \ libxcb-render-util0 \ libxi6 \ libxcomposite-dev \ libxrender-dev \ libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev \ libgstreamer-plugins-good1.0-dev \ gstreamer1.0-plugins-good \ gstreamer1.0-x \ gstreamer1.0-libav \ webp \ rsync } _ensure_folders () { mkdir -p /downloads && \ mkdir -p /builds && \ chmod a+rw /downloads && \ chmod a+rw /builds } download_official_qt() { _ensure_folders && \ curl -L -o /downloads/qt-installer.run \ $QT_MIRROR } install_official_qt () { # XXX: if qt version is changed, Dockerfile should be updated, # as well as qt-installer-noninteractive.qs script. chmod +x /downloads/qt-installer.run && \ xvfb-run /downloads/qt-installer.run \ --script /app/script.qs \ | egrep -v '\[[0-9]+\] Warning: (Unsupported screen format)|((QPainter|QWidget))' && \ ls /opt/qt59/ && \ # cat /opt/qt59/InstallationLog.txt && \ cat /opt/qt59/components.xml } install_qtwebkit () { # Install webkit from https://github.com/annulen/webkit _ensure_folders && \ curl -L -o /downloads/qtwebkit.tar.xz https://github.com/annulen/webkit/releases/download/qtwebkit-5.212.0-alpha2/qtwebkit-5.212.0_alpha2-qt59-linux-x64.tar.xz && \ pushd /builds && \ tar xvfJ /downloads/qtwebkit.tar.xz --keep-newer-files && \ rsync -aP /builds/qtwebkit-5.212.0_alpha2-qt59-linux-x64/* `qmake -query QT_INSTALL_PREFIX` } install_pyqt5 () { _ensure_folders && \ _activate_venv && \ ${_PYTHON} --version && \ curl -L -o /downloads/sip.tar.gz https://sourceforge.net/projects/pyqt/files/sip/sip-${SPLASH_SIP_VERSION}/sip-${SPLASH_SIP_VERSION}.tar.gz && \ curl -L -o /downloads/pyqt5.tar.gz https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-${SPLASH_PYQT_VERSION}/PyQt5_gpl-${SPLASH_PYQT_VERSION}.tar.gz && \ # curl -L -o /downloads/sip.tar.gz https://www.riverbankcomputing.com/static/Downloads/sip/sip-${SPLASH_SIP_VERSION}.tar.gz && \ # curl -L -o /downloads/pyqt5.tar.gz https://www.riverbankcomputing.com/static/Downloads/PyQt5/PyQt5_gpl-${SPLASH_PYQT_VERSION}.tar.gz && \ ls -lh /downloads && \ # TODO: check downloads pushd /builds && \ # SIP tar xzf /downloads/sip.tar.gz --keep-newer-files && \ pushd sip-${SPLASH_SIP_VERSION} && \ ${_PYTHON} configure.py && \ make -j ${SPLASH_BUILD_PARALLEL_JOBS} && \ make install && \ popd && \ # PyQt5 tar xzf /downloads/pyqt5.tar.gz --keep-newer-files && \ pushd PyQt5_gpl-${SPLASH_PYQT_VERSION} && \ # --qmake "${SPLASH_QT_PATH}/bin/qmake" \ ${_PYTHON} configure.py -c \ --verbose \ --confirm-license \ --no-designer-plugin \ --no-qml-plugin \ --no-python-dbus \ -e QtCore \ -e QtGui \ -e QtWidgets \ -e QtNetwork \ -e QtWebKit \ -e QtWebKitWidgets \ -e QtSvg \ -e QtPrintSupport && \ make -j ${SPLASH_BUILD_PARALLEL_JOBS} && \ make install && \ popd && \ # Builds Complete popd } install_python_deps(){ # Install python-level dependencies. _activate_venv && \ ${_PYTHON} -m pip install -U pip setuptools six && \ ${_PYTHON} -m pip install \ qt5reactor==0.4 \ psutil==5.0.0 \ Twisted==16.1.1 \ adblockparser==0.7 \ xvfbwrapper==0.2.9 \ funcparserlib==0.3.6 \ Pillow==3.4.2 \ lupa==1.3 && \ ${_PYTHON} -m pip install https://github.com/sunu/pyre2/archive/c610be52c3b5379b257d56fc0669d022fd70082a.zip#egg=re2 ${_PYTHON} -m pip install -r "$APP_ROOT/slybot/requirements.txt" ${_PYTHON} -m pip install -r "$APP_ROOT/slyd/requirements.txt" ${_PYTHON} -m pip install -r "$APP_ROOT/portia_server/requirements.txt" } install_msfonts() { # Agree with EULA and install Microsoft fonts # apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu xenial multiverse" && \ # apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu xenial-updates multiverse" && \ # apt-get update && \ echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections && \ apt-get install --no-install-recommends -y ttf-mscorefonts-installer } install_extra_fonts() { # Install extra fonts (Chinese and other) apt-get install --no-install-recommends -y \ fonts-liberation \ ttf-wqy-zenhei \ fonts-arphic-gbsn00lp \ fonts-arphic-bsmi00lp \ fonts-arphic-gkai00mp \ fonts-arphic-bkai00mp \ fonts-beng } install_flash () { apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu trusty multiverse" && \ apt-get update && \ apt-get install -y flashplugin-installer } remove_builddeps () { # WARNING: only for Docker, don't run blindly! # Uninstall build dependencies. apt-get remove -y --purge \ python3-dev \ libpython3.5-dev \ libpython3.5 \ libpython3.5-dev \ build-essential \ libre2-dev \ liblua5.2-dev \ zlib1g-dev \ libc-dev \ libjpeg-turbo8-dev \ libcurl3 \ gcc cpp cpp-5 binutils perl rsync && \ apt-get clean -y } remove_extra () { # WARNING: only for Docker, don't run blindly! # Remove unnecessary files. rm -rf \ /builds \ /downloads \ /opt/qt59/Docs \ /opt/qt59/Tools \ /opt/qt59/Examples \ /app/.git \ /usr/share/man \ /usr/share/info \ /usr/share/doc \ /var/lib/apt/lists/* } install_splash(){ cd /tmp curl -L -o splash.tar.gz 'https://github.com/scrapinghub/splash/archive/3.2.x.tar.gz' tar -xvf splash.tar.gz --keep-newer-files cd splash-* _activate_venv prepare_install install_deps install_qtwebkit_deps download_official_qt install_official_qt install_qtwebkit install_pyqt5 install_python_deps pip install . } configure_nginx(){ cp -r $APP_ROOT/nginx/* /etc/nginx sed 's/\/app\//'""${APP_ROOT//\//\\\/}""'\//g' -i /etc/nginx/nginx.conf } configure_initctl(){ cp "$APP_ROOT/portia.conf" /etc/init } migrate_django_db(){ python /vagrant/portia_server/manage.py migrate } start_portia(){ echo "Starting Nginx" echo "==============" /etc/init.d/nginx start echo "Starting Nginx" echo "==============" start portia } install_frontend_deps() { npm install -g bower ember-cli } build_assets() { cd "$APP_ROOT/portiaui" npm install && npm run build } if [ \( $# -eq 0 \) -o \( "$1" = "-h" \) -o \( "$1" = "--help" \) ]; then usage exit 1 fi UNKNOWN=0 for cmd in "$@"; do if [ "$(type -t -- "$cmd")" != "function" ]; then echo "Unknown command: $cmd" UNKNOWN=1 fi done if [ $UNKNOWN -eq 1 ]; then echo "Unknown commands encountered, exiting..." exit 1 fi while [ $# -gt 0 ]; do echo "Executing command: $1" "$1" shift done ================================================ FILE: docker/qt_install.qs ================================================ // Emacs mode hint: -*- mode: JavaScript -*- // https://bitbucket.org/xiannox/trusty-qt5.7-beta-x64/raw/HEAD/qt-installer-noninteractive.qs // https://bitbucket.org/xiannox/trusty-qt5.7-beta-x64 function Controller() { installer.autoRejectMessageBoxes(); installer.installationFinished.connect(function() { gui.clickButton(buttons.NextButton); }) } Controller.prototype.WelcomePageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.CredentialsPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.IntroductionPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.TargetDirectoryPageCallback = function() { gui.currentPageWidget().TargetDirectoryLineEdit.setText("/opt/qt59"); gui.clickButton(buttons.NextButton); } Controller.prototype.ComponentSelectionPageCallback = function() { var widget = gui.currentPageWidget(); // To get component names, comment out widget.deselectAll() // to install everything default, then check components.xml file. widget.deselectAll(); widget.selectComponent("qt.591.gcc_64"); widget.selectComponent("qt.591.qtwebengine.gcc_64"); gui.clickButton(buttons.NextButton); } Controller.prototype.LicenseAgreementPageCallback = function() { gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true); gui.clickButton(buttons.NextButton); } Controller.prototype.StartMenuDirectoryPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.ReadyForInstallationPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.FinishedPageCallback = function() { var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) { checkBoxForm.launchQtCreatorCheckBox.checked = false; } gui.clickButton(buttons.FinishButton); } ================================================ FILE: docker/restore-mtime.sh ================================================ #!/bin/bash commit=$(git rev-list -n 1 HEAD requirements.txt) mtime=$(git show --pretty=format:%ai --abbrev-commit $commit |head -n1) touch -d "$mtime" requirements.txt ================================================ FILE: docker/run-tests.sh ================================================ #!/bin/bash export PYTHONPATH=`pwd`/slybot:`pwd`/slyd pip install tox cd /app/slyd python2.7 tests/testserver/server.py 2>&1 | grep -v 'HTTP/1.1" 200' & sleep 3 cd /app/slybot tox cd /app/portia_server ./manage.py test portia_orm.tests ./manage.py test portia_api.tests ================================================ FILE: docker-compose.yml ================================================ version: '3' services: app: build: . command: /app/docker/entry start-dev volumes: - ./data/projects:/app/data/projects:rw - ./portiaui/dist:/app/portiaui/dist - ./slyd:/app/slyd - ./portia_server:/app/portia_server - ./slybot:/app/slybot ports: - 9001:9001 restart: always ================================================ FILE: docs/Makefile ================================================ # Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Portia.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Portia.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Portia" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Portia" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." ================================================ FILE: docs/conf.py ================================================ # -*- coding: utf-8 -*- # # Portia documentation build configuration file, created by # sphinx-quickstart on Tue Aug 25 13:51:18 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os from datetime import datetime from os import path VERSION_FILE = path.abspath(path.join(path.dirname(__file__), '..', 'VERSION')) YEAR = datetime.now().year with open(VERSION_FILE, 'r') as f: RELEASE = f.read().strip() VERSION = RELEASE.rsplit('.', 1)[0] # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Portia' copyright = u'{}, Scrapinghub'.format(YEAR) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = VERSION # The full version, including alpha/beta/rc tags. release = RELEASE # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all # documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. #html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # 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 = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'Portiadoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'Portia.tex', u'Portia Documentation', u'Scrapinghub', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'portia', u'Portia Documentation', [u'Scrapinghub'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'Portia', u'Portia Documentation', u'Scrapinghub', 'Portia', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False ### Following is taken from https://github.com/snide/sphinx_rtd_theme#using-this-theme-locally-then-building-on-read-the-docs # on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org on_rtd = os.environ.get('READTHEDOCS', None) == 'True' if not on_rtd: # only import and set the theme if we're building docs locally import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # otherwise, readthedocs.org uses their theme by default, so no need to specify it ### end ================================================ FILE: docs/examples.rst ================================================ .. _examples: ======== Examples ======== Crawling paginated listings =========================== Most e-commerce sites use pagination to spread results across multiple pages. When crawling these sites with Portia, there are some best practices you should follow: * Use the target categories as start pages. * Use URL follow patterns to limit Portia to only visit category and article pages. This will prevent Portia from visiting unnecessary pages so you can crawl the items a lot faster. Let's use `timberlandonline.co.uk `_ as an example. Say you want to only scrape products from the `boots `_ and `shoes `_ categories. You can `create a spider `_ and add the categories to its start URLs: .. image:: _static/portia-start-urls.png :target: _static/portia-start-urls.png :alt: Start URLs To ensure the spider only visits relevant pages, you'll need to limit crawling to the target categories and product pages. You can accomplish this defining URL follow patterns in the Link Crawling configuration of your spider: .. image:: _static/portia-follow-patterns.png :target: _static/portia-follow-patterns.png :alt: Follow patterns You can use follow patterns to filter URLs with `regular expressions `_. You can see which links will be followed by clicking the |icon-toggle-links| button (toggle highlighting) to the right of Portia's URL bar. Followed links will be highlighted in green and excluded links in red. .. |icon-toggle-links| image:: _static/portia-icon-toggle-links.png :width: 16px :height: 16px As you can see above, the spider will now only visit the boots and shoes category pages and their product listings. To ensure that only products belonging to the target categories are visited, we filter against the ``catID`` parameter value in the URL. Crawling listings in this manner is much more efficient. You avoid visiting tons of unwanted pages on the site and instead crawl only those you need. Selecting elements with CSS and XPath ===================================== You can select elements with CSS or XPath by changing the selection mode of an annotation. You can do it clicking the |cog-symbol| symbol right to the annotation name in the ``ITEMS`` section of the left sidebar. .. image:: _static/portia-change-selection-mode.png :alt: Changing the selection mode of an annotation. This way, you can tweak your selections, making them more or less specific, for example. .. |cog-symbol| unicode:: 0x2699 Extracting a single attribute to multiple fields ================================================ Portia supports multiple annotations for the same attribute. You can take advantage of this to extract an attribute to multiple fields by simply creating an annotation for each field. Imagine you want to extract the username and the date from blog posts and this information is represented like this: .. code-block:: html
By johndoe on March 3th
To extract this information separately, you have to annotate the element, click the gear icon right after the field name and add an extractor with a regular expression that captures only the username: ``By (\w+).*``. After that, you have to go back to annotation mode, click the |icon-add| button in the toolbar and then annotate the same element again. Now, you have to create another extractor to capture only the date from the element: ``By \w+ on (.*)``. .. |icon-add| image:: _static/portia-icon-add.png :width: 16px :height: 16px Scraping multiple items from a single page ========================================== You'll often need to retrieve several items from a single page. You can do this using either the repeating element tool |portia-icon-add-repeat| or with the wand |portia-icon-wand| by annotating the first item's element and then clicking the second item's element. Portia will detect all similar items on the page and create annotations for each of them. .. |portia-icon-add-repeat| image:: _static/portia-icon-add-repeat.png :width: 16px :height: 16px .. |portia-icon-wand| image:: _static/portia-icon-wand.png :width: 16px :height: 16px Let's revisit the `timerberlandonline.co.uk `_ spider and demonstrate this process by annotating a couple of pairs of shoes. Click the tiles icon to select the repeating element tool and then click an element, and Portia will find all similar elements and link them to the same field: .. image:: _static/portia-multi-preview.png :target: _static/portia-multi-preview.png :alt: Start URLs Now you just need to do same for the other fields, and you're done! .. _multiple-samples-example: Using Multiple Samples to Deal with Different Layouts ===================================================== Some websites use different layouts to display the same kind of information. E-commerce websites usually create special pages for some products on Black Friday, for example. Sometimes, the problem is that some pages might not have all the data you need. You can create multiple samples, even if you are extracting only one item type, to make sure your spider can handle these variations. **Consider this example:** our spider has an item type with the fields ``name``, ``price``, ``description`` and ``manufacturer``, where ``name`` and ``price`` are required fields. We have created a sample with annotations for each of those fields. Upon running the spider, many items are correctly scraped; however, there are a large number of scraped items where the ``manufacturer`` field contains what should be the ``description``, and the ``description`` field is empty. This has been caused by some pages having a different layout: Layout A: .. code-block:: html
name price
manufacturer
description
Layout B: .. code-block:: html
name price
description
As you can see, the problem lies with the fact that in layout B the description is where manufacturer would be, and with ``description`` not being a required field it means that the sample created for layout A will match layout B. Creating a new sample for layout B won't be enough to fix the problem, as layout A's sample :ref:`would contain more annotation and be matched against first `. Instead we need to modify layout A's sample, and mark the ``description`` annotation as **Required**. With this added constraint, items displayed with layout B will not be matched against layout A's sample due to the missing ``description`` field, so the spider will proceed onto layout B's sample which will extract the data successfully. :ref:`Click here to learn more about Multiple Samples `. ================================================ FILE: docs/faq.rst ================================================ .. _faq: FAQ === How do I use Crawlera with Portia? ---------------------------------- Portia spiders are standard Scrapy spiders, so you can enable the `middleware `_ in your project's `settings.py`. Does Portia support AJAX based websites? ---------------------------------------- Yes. Does Portia work with large JavaScript frameworks like Ember? ------------------------------------------------------------- Backbone, Angular, and Ember have all been thoroughly tested using Portia, and in most cases should work fine. React based websites aren't supported yet but we're working on it. Does Portia support sites that require you to log in? ----------------------------------------------------- Yes, you can set credentials in your spider's crawling configuration. Does Portia support content behind search forms? ------------------------------------------------ No, but we plan on adding support in the near future. ================================================ FILE: docs/getting-started.rst ================================================ .. _getting-started: =============== Getting Started =============== .. note:: If you don't have Portia running yet, please read the :ref:`Installation guide ` first. This tutorial will briefly cover how to begin extracting data with Portia. Creating a spider ================= Let's start by creating a project. Enter a URL and Portia will render it like below: .. This tutorial will briefly cover how to retrieve products from Amazon.com_ using Portia. .. .. _amazon.com: http://amazon.com/ .. First, create a Portia project and enter a URL. Portia will render it like below: .. image:: _static/portia-main-page.png :alt: Portia main page Click the ``New spider`` button to create a new spider. Portia will add the page's URL as a start page automatically. Start pages are used to seed the crawl and Portia will visit them when you start the spider to find more links. Creating a sample ================= A sample describes how data should be extracted from the page. Portia will use your samples to extract data from other pages with a similar structure. Portia works like a web browser, so you can navigate between pages as you would normally. Navigate to a page you want to scrape and then the ``New sample`` button to create a :ref:`sample ` of the page. .. image:: _static/portia-new-spider.png :alt: Newly created sample Now that you've created the sample, you can begin :ref:`annotating ` the page. Annotations link a piece of data in the page to an item field. You'll notice that you can highlight elements on the page, if you click on it will create a new field to which the element will be extracted. Portia will create an :ref:`item ` schema from the elements that you annotated and will use it as the data format for the scraped :ref:`items `. .. image:: _static/portia-annotation.png :alt: Annotating a page You can see a preview of the items your sample will extract on the right. Once you've annotated all the data you wish to extract, close the sample. Your spider is :ref:`ready to run `, but you may want to configure it further in which case you should continue reading. Configuring your crawler ======================== To start crawling a website, Portia needs one or more URLs to visit first so it can gather further links to crawl. You can define these URLs on the left under ``START PAGES``. .. image:: _static/portia-add-start-pages.png :alt: Adding start pages Portia follows all in-domain URLs by default. In many cases you'll want to limit the pages Portia will visit so requests aren't wasted on irrelevant pages. To do this, you can set follow and exclude patterns that whitelist and blacklist URLs respectively. These can be configured by changing the crawling policy to ``Configure URL patterns``. For example, Amazon products' URLs contain ``/gp/``, so you can add this as a follow pattern and Portia will know to only follow such URLs. .. image:: _static/portia-configuring-crawling.png :alt: Configuring the crawling What's next? ============ Once you've created your samples and configured crawling behavior, it's time to :ref:`run ` your spider. Check out the :ref:`examples` to learn a few tips to be more productive with Portia. ================================================ FILE: docs/index.rst ================================================ Welcome to Portia's documentation! ================================== Contents: .. toctree:: :maxdepth: 2 installation getting-started examples projects spiders samples items faq Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` ================================================ FILE: docs/installation.rst ================================================ .. _installation: Installation ============ Docker (recommended) -------------------- If you are on a Linux machine you will need `Docker `_ installed or if you are using a `Windows `_ or `Mac OS X `_ machine you will need `boot2docker `_. You can run Portia with the command below:: docker run -i -t --rm -v :/app/data/projects:rw -p 9001:9001 scrapinghub/portia Or with docker-compose by running:: docker compose up Portia will now be running on port 9001 and you can access it at ``http://localhost:9001``. Projects will be stored in the project folder that you mount to docker. To extract data using portia you can run your spider with:: docker run -i -t --rm -v :/app/data/projects:rw -v :/mnt:rw -p 9001:9001 scrapinghub/portia \ portiacrawl /app/data/projects/PROJECT_NAME SPIDER_NAME -o /mnt/SPIDER_NAME.jl After the crawl finishes you will find your extracted data in the the `OUTPUT_FOLDER` .. note:: ** and ** are just paths on your system where your projects and extracted data are stored. .. warning:: For Windows the ** path must be of the form */*. For example */C/Users/UserName/Documents/PortiaProjects* Vagrant ------- Checkout the repository:: $ git clone https://github.com/scrapinghub/portia You will need `Vagrant `_ , `VirtualBox `_ `Node.js `_, `Bower `_ and `ember-cli `_ installed. Run the following in Portia's directory:: docker/compile-assets.sh vagrant up This will launch an Ubuntu virtual machine, build Portia and start the ``portia`` server. You'll then be able to access Portia at ``http://localhost:9001``. You can stop the ``portia`` server using ``vagrant suspend`` or ``vagrant halt``. To run ``portiacrawl`` you will need to SSH into the virtual machine by running ``vagrant ssh``. Ubuntu ------ Running Portia Locally ^^^^^^^^^^^^^^^^^^^^^^ **These instructions are only valid for an Ubuntu based OS** Install the following dependencies:: sudo ./provision.sh install_deps If you would like to run Portia locally you should create an environment with virtualenv:: virtualenv YOUR_ENV_NAME --no-site-packages source YOUR_ENV_NAME/bin/activate cd ENV_NAME Now clone this repository into that env:: git clone https://github.com/scrapinghub/portia.git cd portia Install splash and the required packages:: sudo ./provision.sh install_deps install_splash install_python_deps To run Portia start slyd and portia_server:: PYTHONPATH='/vagrant/portia_server:/vagrant/slyd:/vagrant/slybot' slyd/bin/slyd -p 9002 -r portiaui/dist & portia_server/manage.py runserver Portia should now be running on port 9001 and you can access it at ``http://localhost:9001``. Developing Portia using Docker ------------------------------ To develop Portia using docker you will need `Node.js `_, `Bower `_ and `ember-cli `_ installed. To set up Portia for development use the commands below:: mkdir ~/data git clone git@github.com:scrapinghub/portia.git cd portia/portiaui npm install && bower install cd node_modules/ember-cli && npm install && cd ../../ ember build cd .. docker build . -t portia You can run it using:: docker run -i -t --rm -p 9001:9001 \ -v ~/data:/app/data/projects:rw \ -v ~/portia/portiaui/dist:/app/portiaui/dist \ -v ~/portia/slyd:/app/slyd \ -v ~/portia/portia_server:/app/portia_server \ portia This sets up the ``portia_server`` to restart with every change you make and if you run ``cd ~/portia/portiaui && ember build -w`` in another shell you can rebuild the Portia assets with every change too. ================================================ FILE: docs/items.rst ================================================ .. _items: ===== Items ===== An item refers to a single item of data scraped from the target website. A common example of an item would be a product for sale on an e-commerce website. It's important to differentiate **item** and **item definition**. In Portia, an item definition or item type refers to the schema of an item rather than the item itself. For example, ``book`` would be an item definition, and a specific book scraped from the website would be an item. An item definition consists of multiple fields, so using the example of a product you might have fields named ``name``, ``price``, ``manufacturer`` and so on. We use annotations to extract data from the page into each of these fields. To ensure certain fields are extracted, you can set the **Required** flag on each required field. Portia will discard an item if any required fields are missing. Portia will also remove any duplicate items by default. In some cases you may have fields where the value can vary despite being the same item, in which case you can mark them as **Vary**. This will ignore the field when checking for duplicates. It’s important to only use **Vary** when necessary, as misuse could easily lead to duplicate items being stored. The ``url`` field is a good example of where **Vary** is useful, as the same item may have multiple URLs. If the ``url`` field wasn’t marked as **Vary**, each duplicate item would be seen as unique because its URL would be different. Field types =========== You can set a field's type to ensure it will only match that kind of data. The following field types are available: ========= =========== type description ========= =========== text Plain text. Any markup is stripped and text within nested elements is also extracted. number A numeric value e.g. 7, 9.59. image An image URL. In most cases you will want to map an ``img`` element's ``src`` attribute. price The same as ``number``, a numeric value. raw html Non-sanitized HTML. safe html Sanitized HTML. See below for more details. geopoint The same as ``text``. url A URL. date A date value parsed by `dateparser `_. Won't work if the annotated element has non-date text. ========= =========== The ``safe html`` field type keeps the following elements: ``br``, ``p``, ``big``, ``em``, ``small``, ``strong``, ``sub``, ``sup``, ``ins``, ``del``, ``code``, ``kbd``, ``samp``, ``tt``, ``var``, ``pre``, ``listing``, ``plaintext``, ``abbr``, ``acronym``, ``address``, ``bdo``, ``blockquote``, ``q``, ``cite``, ``dfn``, ``table``, ``tr``, ``th``, ``td``, ``tbody``, ``ul``, ``ol``, ``li``, ``dl``, ``dd``, ``dt``. All other elements are discarded, with the exception of header tags (``h1``, ``h2`` ... ``h6``) and ``b`` which are replaced with ``strong``, and ``i`` which is replaced with ``em``. Whitelisted elements contained within non-whitelisted elements will still be retained, with the exception of elements contained within a ``script``, ``img`` or ``input`` element. For example, ``
example
`` would extract to ``example``, whereas ```` would be discarded completely. ================================================ FILE: docs/make.bat ================================================ @ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Portia.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Portia.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end ================================================ FILE: docs/projects.rst ================================================ .. _projects: ======== Projects ======== A project in Portia consists of one or more :ref:`spiders ` and can be deployed to any `scrapyd`_ instance. Versioning ========== .. _project-deployment: Portia provides project versioning via Git, but this isn't enabled by default. Git versioning can be enabled by creating a `local_settings.py` file in the `slyd/slyd` directory and adding the following: .. code-block:: python import os SPEC_FACTORY = { 'PROJECT_SPEC': 'slyd.gitstorage.projectspec.ProjectSpec', 'PROJECT_MANAGER': 'slyd.gitstorage.projects.ProjectsManager', 'PARAMS': { 'storage_backend': 'dulwich.repo.Repo', 'location': os.environ.get('PORTIA_DATA_DIR', SPEC_DATA_DIR) }, 'CAPABILITIES': { 'version_control': True, 'create_projects': True, 'delete_projects': True, 'rename_projects': True } } You can also use MySQL to store your project files in combination with Git: .. code-block:: python import os SPEC_FACTORY = { 'PROJECT_SPEC': 'slyd.gitstorage.projectspec.ProjectSpec', 'PROJECT_MANAGER': 'slyd.gitstorage.projects.ProjectsManager', 'PARAMS': { 'storage_backend': 'slyd.gitstorage.repo.MysqlRepo', 'location': os.environ.get('DB_URL'), }, 'CAPABILITIES': { 'version_control': True, 'create_projects': True, 'delete_projects': True, 'rename_projects': True } } This will store versioned projects as blobs within the MySQL database that you specify by setting the environment variable below:: DB_URL = mysql://:@:/ When this env variable is set the database can be initialized by running the bin/init_mysqldb script. .. note:: The MySQL backend only stores project data. Data generated during crawl is still stored locally. Deployment ========== You can deploy your Portia projects using `scrapyd`_. Change directory into ``slyd/data/projects/PROJECT_NAME`` and add your target to ``scrapy.cfg``. You'll then be able to run ``scrapyd-deploy`` which will deploy your project using the default deploy target. Alternatively, you can specify a target and project using the following:: scrapyd-deploy your_scrapyd_target -p project_name Once your spider is deployed, you can schedule your spider via ``schedule.json``:: curl http://your_scrapyd_host:6800/schedule.json -d project=your_project_name -d spider=your_spider_name .. warning:: Running scrapyd from your project directory will cause deployment to fail. .. _scrapyd: https://scrapyd.readthedocs.org/en/latest/ ================================================ FILE: docs/samples.rst ================================================ .. _samples: ======= Samples ======= What are samples? ================= When the crawler visits a page, it matches the page against each sample. Samples with more annotations take precedence over those with less. If the page matches a sample, it will use the sample's annotations to extract data. Assuming all required fields are filled, it will yield an item. Spiders consist of one or more samples and each sample is made up of annotations that define the elements you wish to extract. Within the sample you define the item you want to extract and mark required fields for that item. .. _what-are-annotations: What are annotations? ===================== An annotation defines the location of a piece of data on the web page and how it should be used by the spider. Typically an annotation maps some element on the page to a particular field of an item, but there is also the option to mark the data as being required without storing the data in an item. It's possible to map attributes of a particular element instead of the content if this is required, for example you can map the ``href`` attribute of an anchor link rather than the text. Annotations =========== Creating annotations -------------------- You can create annotations by clicking an element on the page with the appropriate tool selected. You should use the wand (|icon-wand|) most of the time as it will select the appropriate tool automatically. The following tools are available: * |icon-wand| - Select the most appropriate tool when clicking on an element * |icon-select| - Select an element * |icon-add| - Add an element * |icon-sub| - Remove an element * |icon-add-repeat| - Add repeating element .. |icon-wand| image:: _static/portia-icon-wand.png :width: 16px :height: 16px .. |icon-select| image:: _static/portia-icon-pointer.png :width: 16px :height: 16px .. |icon-add| image:: _static/portia-icon-add.png :width: 16px :height: 16px .. |icon-sub| image:: _static/portia-icon-sub.png :width: 16px :height: 16px .. |icon-add-repeat| image:: _static/portia-icon-add-repeat.png :width: 16px :height: 16px Extractors ---------- You can also add extractors to annotations. Extractors let you use regular expressions or a pre-defined type to further refine data extracted from a page. For example, assume there's an element that contains a phone number, but it has additional text that you don't need. In this scenario you could add an extractor to retrieve only the phone number instead of the full text. You can define the extractor for a particular field by clicking in the gear icon right after the field type: .. image:: _static/portia-goto-extractors.png :alt: Field extractors And then you can select use any built-in extractors or create your own extractor via regular expressions: .. image:: _static/portia-extractors.png :alt: Field extractors Multiple fields --------------- It's possible to extract multiple fields using a single annotation if there are several properties you want to extract from an element. For example, if there was an image you wanted, you could map the ``src`` attribute that contains the image URL to one field, and the ``alt`` attribute to another. You can do it in the ``Inspector`` panel in the top left of the screen: .. image:: _static/portia-sample-multiple-fields.png :alt: Multiple fields from one element Just click the ``+`` button right after an attribute to add a new field based on the same annotation. .. _multiple-samples: Multiple samples ================ It's often necessary to use multiple samples within one spider, even if you're only extracting one item type. Some pages containing the same item type may have a different layout or fields missing, and you will need to accommodate for those pages by creating a sample for each variation in layout. Sample precedence ----------------- The more annotations a sample has, the more specific the data being extracted and therefore less chance of a false positive. For this reason, samples with more annotations take precedence over those with less annotations. If a subset of samples contains equal number of annotations per sample, then within that subset samples will be tried in the order they were created from first to last. In other words, samples are tried sequentially in order of number of annotations first, and age second. If you are working with a large number of samples, it may be difficult to ensure the correct sample is applied to the right page. It's best to keep samples as strict as possible to avoid any false matches. It's useful to take advantage of the ``Required`` option from item fields and annotate elements that will always appear on matching pages to reduce the number of false positives. **Check this example** to learn how to do it: :ref:`multiple-samples-example`. ================================================ FILE: docs/spiders.rst ================================================ .. _spiders: ======= Spiders ======= Spiders are web crawlers that use :ref:`samples ` to extract data from the pages it visits. .. _spider-properties: Spider properties ================= You can access your spider's properties by clicking the gear icon located right of your spider in the list on the left. .. image:: _static/portia-spider-properties.png :alt: Spider properties Configuring login details ------------------------- If you need to log into a site, you can configure login details by ticking 'Perform login' in the :ref:`spider properties ` menu. Here you can set the login URL, username and password. Enabling JavaScript ------------------- You can enable JavaScript in your spider by ticking ``Enable JavaScript`` in the :ref:`spider properties ` menu. Note that you'll need to set the ``SPLASH_URL`` Scrapy setting to your [Splash](https://github.com/scrapinghub/splash) endpoint URL for JavaScript to work during the crawl. Start pages and link crawling ============================= Start pages are the initial URLs that Portia will visit to start the crawl. You can add and remove start pages on the left menu. You can choose how Portia will follow links under ``LINK CRAWLING``. .. image:: _static/portia-spider-link-crawling.png :alt: Link crawling properties * Follow all in-domain links - follow all links under the same domain and subdomain. * Don't follow links - only visit start URLs. * Configure url patterns - use regular expressions to choose which URLs to follow. The ``Configure url patterns`` option lets you set follow and exclude patterns as well as choose whether to respect the ``nofollow`` attribute. Click the gear icon to show the link crawling options where you can set the follow/exclude patterns. .. _running-spider: Running a spider ================ Portia will save your projects in ``slyd/data/projects``. You can use ``portiacrawl`` to run a spider:: portiacrawl PROJECT_PATH SPIDER_NAME where ``PROJECT_PATH`` is the path of the project and ``SPIDER_NAME`` is a spider that exists within that project. You can list the spiders for a project with the following:: portiacrawl PROJECT_PATH Portia spiders are ultimately `Scrapy `_ spiders. You can pass Scrapy arguments when running with ``portiacrawl`` using the ``-a`` option. You can also specify a custom settings module using the ``--settings`` option. The `Scrapy documentation `_ contains full details on available options and settings. Minimum items threshold ======================= To avoid infinite crawling loops, Portia spiders check to see if the number of scraped items meet a minimum threshold over a given period of time. If not, the job is closed with ``slybot_fewitems_scraped`` outcome. By default, the period of time is 3600 seconds and the threshold is 200 items scraped. This means if less than 200 items were scraped in the last 3600 seconds, the job will close. You can set the period in seconds with the ``SLYCLOSE_SPIDER_CHECK_PERIOD`` setting, and the threshold number of items with the ``SLYCLOSE_SPIDER_PERIOD_ITEMS`` setting. ================================================ FILE: portia_server/db_repo/__init__.py ================================================ ================================================ FILE: portia_server/db_repo/apps.py ================================================ from __future__ import unicode_literals from django.apps import AppConfig class DbRepoConfig(AppConfig): name = 'db_repo' ================================================ FILE: portia_server/db_repo/migrations/0001_initial.py ================================================ # -*- coding: utf-8 -*- # Generated by Django 1.10 on 2016-10-04 06:54 from __future__ import unicode_literals import db_repo.models from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='Objs', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('oid', db_repo.models.RealBinaryField(default='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', max_length=40)), ('repo', models.CharField(max_length=64)), ('type', db_repo.models.PositiveTinyIntegerField(db_index=True)), ('size', db_repo.models.PositiveBigIntegerField(db_index=True)), ('data', db_repo.models.CompressedBinaryField()), ], options={ 'db_table': 'objs', }, ), migrations.CreateModel( name='Refs', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('ref', models.CharField(default='', max_length=100)), ('repo', models.CharField(max_length=64)), ('value', db_repo.models.RealBinaryField(db_index=True, max_length=40)), ], options={ 'db_table': 'refs', }, ), migrations.AlterUniqueTogether( name='refs', unique_together=set([('ref', 'repo')]), ), migrations.AlterUniqueTogether( name='objs', unique_together=set([('oid', 'repo')]), ), ] ================================================ FILE: portia_server/db_repo/migrations/__init__.py ================================================ ================================================ FILE: portia_server/db_repo/migrations/slyd_to_django.sql ================================================ ALTER TABLE `objs` DROP PRIMARY KEY, ADD COLUMN `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, ADD CONSTRAINT `objs_oid_feda89ac_uniq` UNIQUE (`oid`, `repo`), CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, ALTER COLUMN `oid` DROP DEFAULT; DROP INDEX `type` ON `objs`; DROP INDEX `size` ON `objs`; CREATE INDEX `objs_599dcce2` ON `objs` (`type`); CREATE INDEX `objs_f7bd60b7` ON `objs` (`size`); ALTER TABLE `refs` DROP PRIMARY KEY, ADD COLUMN `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, ADD CONSTRAINT `refs_ref_4a751775_uniq` UNIQUE (`ref`, `repo`), CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, ALTER COLUMN `ref` DROP DEFAULT; DROP INDEX `value` ON `refs`; CREATE INDEX `refs_2063c160` ON `refs` (`value`); ================================================ FILE: portia_server/db_repo/models.py ================================================ from __future__ import unicode_literals from django.db.models import (Model, BinaryField, BigIntegerField, PositiveSmallIntegerField, CharField) from django.db.models.expressions import Func, Value class PositiveTinyIntegerField(PositiveSmallIntegerField): def db_type(self, connection): if connection.vendor == 'mysql': return "tinyint(1) unsigned" else: return super(PositiveTinyIntegerField, self).db_type(connection) class PositiveBigIntegerField(BigIntegerField): def db_type(self, connection): if connection.vendor == 'mysql': return "bigint(20) unsigned" else: return super(PositiveBigIntegerField, self).db_type(connection) class RealBinaryField(BinaryField): def db_type(self, connection): if connection.vendor == 'mysql': return "binary({})".format(self.max_length) else: return super(RealBinaryField, self).db_type(connection) class CompressedBinaryField(BinaryField): def get_db_prep_save(self, value, connection): prepped_value = super(CompressedBinaryField, self).get_db_prep_save( value, connection) if connection.vendor == 'mysql': return Func(Value(prepped_value), function='COMPRESS') return prepped_value def select_format(self, compiler, sql, params): sql, params = super(CompressedBinaryField, self).select_format( compiler, sql, params) if compiler.connection.vendor == 'mysql': sql = 'UNCOMPRESS({})'.format(sql) return sql, params class Objs(Model): oid = RealBinaryField(max_length=40, default='\0' * 40, null=False) repo = CharField(max_length=64, null=False) type = PositiveTinyIntegerField(null=False, db_index=True) size = PositiveBigIntegerField(null=False, db_index=True) data = CompressedBinaryField(null=False) class Meta(object): unique_together = (('oid', 'repo'),) db_table = 'objs' class Refs(Model): ref = CharField(max_length=100, default='', null=False) repo = CharField(max_length=64, null=False) value = RealBinaryField(max_length=40, null=False, db_index=True) class Meta(object): unique_together = (('ref', 'repo'),) db_table = 'refs' ================================================ FILE: portia_server/db_repo/repo.py ================================================ from django.db.transaction import get_autocommit from django.db.utils import IntegrityError from dulwich.errors import ObjectMissing from dulwich.object_store import BaseObjectStore, MemoryObjectStore from dulwich.objects import sha_to_hex from dulwich.repo import BaseRepo, MemoryRepo from dulwich.refs import DictRefsContainer, RefsContainer, SYMREF from six import get_unbound_function from .models import Objs, Refs class MysqlObjectStore(BaseObjectStore): """Object store that keeps all objects in a mysql database.""" def __init__(self, repo): super(MysqlObjectStore, self).__init__() self._repo = repo add_objects = get_unbound_function(MemoryObjectStore.add_objects) add_thin_pack = get_unbound_function(MemoryObjectStore.add_thin_pack) contains_packed = get_unbound_function(MemoryObjectStore.contains_packed) packs = MemoryObjectStore.packs _complete_thin_pack = get_unbound_function( MemoryObjectStore._complete_thin_pack) def _to_hexsha(self, sha): if len(sha) == 40: return sha elif len(sha) == 20: return sha_to_hex(sha) else: raise ValueError("Invalid sha %r" % (sha,)) def _has_sha(self, sha): """Look for the sha in the database.""" return Objs.objects.filter(repo=self._repo, oid=sha).exists() def _all_shas(self): """Return all db sha keys.""" for obj in Objs.objects.filter(repo=self._repo).only('oid').iterator(): yield obj.oid def contains_loose(self, sha): """Check if a particular object is present by SHA1 and is loose.""" return self._has_sha(self._to_hexsha(sha)) def __iter__(self): """Iterate over the SHAs that are present in this store.""" return self._all_shas() def get_raw(self, name): """Obtain the raw text for an object. :param name: sha for the object. :return: tuple with numeric type and object contents. """ try: obj = Objs.objects.only('type', 'data')\ .get(repo=self._repo, oid=self._to_hexsha(name)) except Objs.DoesNotExist: # last resort fallback, this exception will cause a retry raise ObjectMissing(name) else: return obj.type, obj.data def add_object(self, obj): data = obj.as_raw_string() oid = obj.id tnum = obj.get_type() try: Objs.objects.update_or_create( repo=self._repo, oid=oid, type=tnum, size=len(data), data=data) except IntegrityError: pass def delete_objects(self, object_ids): Objs.objects.filter(repo=self._repo, oid__in=object_ids).delete() class MysqlRefsContainer(RefsContainer): """RefsContainer backed by MySql. This container does not support packed references. """ def __init__(self, repo): super(MysqlRefsContainer, self).__init__() self._repo = repo get_packed_refs = get_unbound_function(DictRefsContainer.get_packed_refs) def allkeys(self): for ref in Refs.objects.filter(repo=self._repo).only('ref').iterator(): yield ref.ref def read_loose_ref(self, name): qs = Refs.objects.only('value') if not get_autocommit(using=qs._db): qs = qs.select_for_update() try: ref = qs.get(repo=self._repo, ref=name) except Refs.DoesNotExist: return None else: return ref.value def set_symbolic_ref(self, name, other): self._update_ref(name, SYMREF + other) def set_if_equals(self, name, old_ref, new_ref): if old_ref is not None and self.read_loose_ref(name) != old_ref: return False realnames, _ = self.follow(name) for realname in realnames: self._check_refname(realname) self._update_ref(realname, new_ref) return True def add_if_new(self, name, ref): if self.read_loose_ref(name): return False self._update_ref(name, ref) return True def remove_if_equals(self, name, old_ref): if old_ref is not None and self.read_loose_ref(name) != old_ref: return False self._remove_ref(name) return True def _update_ref(self, name, value): Refs.objects.update_or_create(repo=self._repo, ref=name, defaults={ 'value': value, }) def _remove_ref(self, name): Refs.objects.filter(repo=self._repo, ref=name).delete() class MysqlRepo(BaseRepo): """Repo that stores refs, objects, and named files in MySql. MySql repos are always bare: they have no working tree and no index, since those have a stronger dependency on the filesystem. """ def __init__(self, name): self._name = name BaseRepo.__init__(self, MysqlObjectStore(name), MysqlRefsContainer(name)) self.bare = True open_index = get_unbound_function(MemoryRepo.open_index) def head(self): """Return the SHA1 pointed at by HEAD.""" return self.refs['refs/heads/master'] @classmethod def init_bare(cls, name): """Create a new bare repository.""" return cls(name) @classmethod def open(cls, name): """Open an existing repository.""" return cls(name) @classmethod def repo_exists(cls, name): """Check if a repository exists.""" return Objs.objects.filter(repo=name).exists() @classmethod def list_repos(cls): """List all repository names.""" return Objs.objects.distinct().values_list('repo', flat=True) @classmethod def delete_repo(cls, name): """Delete a repository.""" Objs.objects.filter(repo=name).delete() Refs.objects.filter(repo=name).delete() ================================================ FILE: portia_server/manage.py ================================================ #!/usr/bin/env python3 import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "portia_server.settings") from django.core.management import execute_from_command_line execute_from_command_line(sys.argv) ================================================ FILE: portia_server/portia_api/__init__.py ================================================ ================================================ FILE: portia_server/portia_api/apps.py ================================================ from __future__ import unicode_literals from django.apps import AppConfig class PortiaApiConfig(AppConfig): name = 'portia_api' ================================================ FILE: portia_server/portia_api/errors.py ================================================ class BaseError(Exception): def __init__(self, status, title, body=''): self._status = status self._title = title self._body = body @property def title(self): return self._title @property def body(self): return self._body @property def status(self): return self._status def __repr__(self): return '%s(%s)' % (self.__class__.__name__, str(self)) def __str__(self): return '%s: %s' % (self.status, self.title) class BaseHTTPError(BaseError): _status = 999 def __init__(self, title, body=''): super(BaseHTTPError, self).__init__(self._status, title, body) class BadRequest(BaseHTTPError): _status = 400 class Forbidden(BaseHTTPError): _status = 403 class NotFound(BaseHTTPError): _status = 404 class InternalServerError(BaseHTTPError): _status = 500 ================================================ FILE: portia_server/portia_api/jsonapi/__init__.py ================================================ from .response import JSONResponse ================================================ FILE: portia_server/portia_api/jsonapi/exceptions.py ================================================ from collections import OrderedDict from uuid import uuid4 from rest_framework.exceptions import APIException, ValidationError from rest_framework.status import (HTTP_400_BAD_REQUEST, HTTP_409_CONFLICT, HTTP_404_NOT_FOUND) from rest_framework.views import exception_handler from .utils import get_status_title class JsonApiValidationError(ValidationError): def __init__(self, detail): super(JsonApiValidationError, self).__init__({ 'errors': [OrderedDict([ ('status', self.status_code), ('title', get_status_title(self.status_code)), ('detail', error['detail']), ('source', error['source']), ]) for error in detail.get('errors', [])] }) def render_exception(status_code, detail): return { 'errors': [OrderedDict([ ('id', str(uuid4())), ('status', status_code), ('title', get_status_title(status_code)), ('detail', detail) ])] } class JsonApiBadRequestError(APIException): status_code = HTTP_400_BAD_REQUEST default_detail = (u"The server cannot process the request due to invalid " u"data.") class JsonApiNotFoundError(APIException): status_code = HTTP_404_NOT_FOUND default_detail = u"Could not find the resource specified" class JsonApiConflictError(APIException): status_code = HTTP_409_CONFLICT default_detail = u"The server cannot process the request due to a conflict." class JsonApiFeatureNotAvailableError(JsonApiBadRequestError): default_detail = u"This feature is not available for your project." class JsonApiGeneralException(APIException): def __init__(self, detail=None, status_code=None): assert status_code is not None self.status_code = status_code super(JsonApiGeneralException, self).__init__(detail) def jsonapi_exception_handler(exc, context): accepts = context['request'].accepted_media_type or '' if accepts.startswith('application/vnd.api+json'): try: exc.detail = render_exception(exc.status_code, exc.detail) except AttributeError: pass # Ignore django exceptions response = exception_handler(exc, context) return response ================================================ FILE: portia_server/portia_api/jsonapi/parsers.py ================================================ from __future__ import unicode_literals from rest_framework.parsers import JSONParser class JSONApiParser(JSONParser): media_type = 'application/vnd.api+json' ================================================ FILE: portia_server/portia_api/jsonapi/registry.py ================================================ from portia_orm.exceptions import ImproperlyConfigured __all__ = [ 'schema', ] schemas = {} def get_schema(schema_type): try: return schemas[schema_type] except KeyError: raise ImproperlyConfigured( u"No schema for type '{}' exists".format(schema_type)) ================================================ FILE: portia_server/portia_api/jsonapi/relationships.py ================================================ from marshmallow_jsonapi.fields import Relationship as BaseRelationship from portia_api.jsonapi.registry import get_schema from portia_api.jsonapi.utils import ( TOP_LEVEL_OBJECT_ORDER, LINKS_OBJECT_ORDER, type_from_model_name, order_dict, cached_property, cached_property_ignore_set) class Relationship(BaseRelationship): def __init__(self, **kwargs): self._serializer = kwargs.get('serializer') super(Relationship, self).__init__(**kwargs) @cached_property def schema(self): schema = self._serializer or get_schema(self.type_) return schema(fields_map=self.root.fields_map, exclude_map=self.root.exclude_map, include_data=self.root.include_map.get(self.name, []), include_data_map=self.root.include_data_map) @cached_property_ignore_set def include_resource_linkage(self): return self.name in self.root.relationship_set def get_related_url(self, obj): if self.related_url: try: return self.related_url.format(self=obj) except AttributeError: pass return None def get_self_url(self, obj): if self.self_url: try: return self.self_url.format(self=obj) except AttributeError: pass return None def get_resource_linkage(self, value): data = super(Relationship, self).get_resource_linkage(value) if self.many: return [order_dict(item, TOP_LEVEL_OBJECT_ORDER) for item in data] return order_dict(data, TOP_LEVEL_OBJECT_ORDER) def _serialize(self, value, attr, obj): data = super(Relationship, self)._serialize(value, attr, obj) if 'links' in data: data['links'] = order_dict(data['links'], LINKS_OBJECT_ORDER) return order_dict(data, TOP_LEVEL_OBJECT_ORDER) class PolymorphicRelationship(Relationship): def __init__(self, **kwargs): super(PolymorphicRelationship, self).__init__(**kwargs) def _serialize(self, value, attr, obj): if not self.many: value = [value] links = None result = [] if value: for instance in value: field = Relationship( type_=type_from_model_name(instance.__class__.__name__), id_field='pk', self_url=self.self_url, related_url=self.related_url, many=False) field._add_to_schema(self.name, self.parent) field.include_data = self.include_data data = field._serialize(instance, attr, obj) if links is None and 'links' in data: links = data['links'] result.append(data.get('data')) else: data = super(PolymorphicRelationship, self)._serialize( None, attr, obj) if links is None and 'links' in data: links = data['links'] if not self.many: result = result[0] data = {} if links is not None: data['links'] = order_dict(links, LINKS_OBJECT_ORDER) if self.include_resource_linkage or self.include_data: data['data'] = result return order_dict(data, TOP_LEVEL_OBJECT_ORDER) def _deserialize(self, value, attr, data): return value ================================================ FILE: portia_server/portia_api/jsonapi/renderers.py ================================================ from __future__ import unicode_literals from rest_framework.renderers import JSONRenderer as BaseJSONRenderer class JSONRenderer(BaseJSONRenderer): default_indent = 2 def get_indent(self, accepted_media_type, renderer_context): indent = super(JSONRenderer, self).get_indent( accepted_media_type, renderer_context) if indent is None: return self.default_indent return indent class JSONApiRenderer(JSONRenderer): media_type = 'application/vnd.api+json' def render(self, data, accepted_media_type=None, renderer_context=None): ret = super(JSONApiRenderer, self).render(data, accepted_media_type, renderer_context) response = renderer_context['response'] content_type = self.media_type try: profiles = data['links']['profile'] except (TypeError, KeyError): profiles = [] if profiles: content_type += '; profile="{}"'.format(' '.join(profiles)) response['Content-Type'] = content_type return ret ================================================ FILE: portia_server/portia_api/jsonapi/response.py ================================================ from django.http import HttpResponse from rest_framework.renderers import JSONRenderer class JSONResponse(HttpResponse): """ An HttpResponse that renders its content into JSON. """ def __init__(self, data, **kwargs): content = JSONRenderer().render(data) kwargs['content_type'] = 'application/json' super(JSONResponse, self).__init__(content, **kwargs) ================================================ FILE: portia_server/portia_api/jsonapi/serializers.py ================================================ from collections import defaultdict, OrderedDict from functools import partial from itertools import chain from operator import itemgetter from marshmallow import pre_dump, post_dump, ValidationError from marshmallow.fields import Method from marshmallow.schema import SchemaMeta from marshmallow_jsonapi import Schema as BaseSchema, SchemaOpts from marshmallow_jsonapi.exceptions import IncorrectTypeError from six import iteritems, iterkeys, string_types, with_metaclass from six.moves import map, zip from portia_api.jsonapi.registry import schemas, get_schema from portia_api.jsonapi.relationships import ( Relationship, PolymorphicRelationship) from portia_api.jsonapi.utils import ( RESOURCE_OBJECT_ORDER, TOP_LEVEL_OBJECT_ORDER, cached_property, camel_case_to_dashes, deep_getattr, dasherize, order_dict, should_include_field, type_from_model_name) from portia_orm.base import AUTO_PK, Model from portia_orm.exceptions import ImproperlyConfigured from portia_orm.fields import Field as OrmField from portia_orm.relationships import BaseRelationship, HasMany __all__ = [ 'JsonApiSerializer', 'JsonApiPolymorphicSerializer', ] DELETED_PROFILE = 'https://portia.scrapinghub.com/jsonapi/extensions/deleted' UPDATES_PROFILE = 'https://portia.scrapinghub.com/jsonapi/extensions/updates' DELETED_PROFILE_ALIAS = 'deleted' UPDATES_PROFILE_ALIAS = 'updates' class JsonApiSerializerMeta(SchemaMeta): """Meta class for JSON API schemas.""" def __new__(mcs, name, bases, attrs): parents = [b for b in bases if isinstance(b, JsonApiSerializerMeta)] if not parents: return super(JsonApiSerializerMeta, mcs).__new__( mcs, name, bases, attrs) meta = attrs.pop('Meta', None) try: model = meta.model except AttributeError: raise TypeError( u"Class '{}' is missing the 'Meta.model' attribute.".format( name)) schema_type = type_from_model_name(model.__name__) meta_bases = (meta, object) if meta else (object,) schema_attrs = { 'Meta': type('Meta', meta_bases, { 'type_': schema_type, 'inflect': dasherize, }) } links = getattr(meta, 'links', {}) for attrname, field in iteritems(model._fields): if isinstance(field, OrmField): field_copy = object.__new__(field.__class__) field_copy.__dict__ = dict(field.__dict__) field_copy.load_from = None field_copy.dump_to = None schema_attrs[attrname] = field_copy elif isinstance(field, BaseRelationship): rel_links = links.get(attrname, {}) rel_many = isinstance(field, HasMany) rel_options = { 'self_url': rel_links.get('self', ''), 'related_url': rel_links.get('related', ''), 'many': rel_many } if not rel_many: rel_options['allow_none'] = True if field.polymorphic: schema_attrs[attrname] = PolymorphicRelationship( **rel_options) else: schema_attrs[attrname] = Relationship( type_=type_from_model_name(field.model.__name__), id_field='pk', serializer=rel_links.get('serializer'), **rel_options) if 'id' not in schema_attrs: pk_field = model._fields[model._pk_field] schema_attrs['id'] = type(pk_field)(attribute=model._pk_field) # we need to access the serialized object to generate the url, but # get_resource_links takes the serialized item, so we add a method field # to do the work schema_attrs['_url'] = Method('get_url') attrs.update(schema_attrs) cls = super(JsonApiSerializerMeta, mcs).__new__(mcs, name, bases, attrs) # add new schema to registry by type is_custom = name.replace('Serializer', '') != model.__name__ key = camel_case_to_dashes(name) if is_custom else schema_type schemas[key] = cls return cls class JsonApiSerializerOpts(SchemaOpts): def __init__(self, meta): super(JsonApiSerializerOpts, self).__init__(meta) if meta is BaseSchema.Meta: return self.strict = True # the model from which the Schema was created, required self.model = getattr(meta, 'model', None) if not issubclass(self.model, Model): raise ValueError("'model' option must be a orm.Model.") # url for an object instance self.url = getattr(meta, 'url', None) if not isinstance(self.url, string_types): raise ValueError("'url' option must be a string.") # default context for serialization self.default_kwargs = getattr(meta, 'default_kwargs', {}) if not isinstance(self.default_kwargs, dict): raise ValueError("'default_kwargs' option must be a dictionary.") class JsonApiSerializer(with_metaclass(JsonApiSerializerMeta, BaseSchema)): OPTIONS_CLASS = JsonApiSerializerOpts def __init__(self, instance=None, data=None, storage=None, only=(), **kwargs): default_kwargs = dict(self.opts.default_kwargs) fields_map = dict(default_kwargs.pop('fields_map', {}), **kwargs.pop('fields_map', {})) exclude_map = dict(default_kwargs.pop('exclude_map', {}), **kwargs.pop('exclude_map', {})) include_data_map = dict(default_kwargs.pop('include_data_map', {}), **kwargs.pop('include_data_map', {})) kwargs = dict(default_kwargs, **kwargs) self.current_url = kwargs.pop('current_url', None) self.include = kwargs.pop('include_data', []) self.ordering = kwargs.pop('ordering', []) self.fields_map = fields_map self.exclude_map = exclude_map self.include_data_map = include_data_map type_ = self.opts.type_ model = self.opts.model self.include_map = include_map = defaultdict(list) for include in chain(self.include, self.include_data_map.get(type_, [])): parts = include.split('.', 1) prefix_map = include_map[parts[0]] if len(parts) == 2: prefix_map.append(parts[1]) field_names = model._field_names relationship_names = model._relationship_names fields = fields_map.get(type_) exclude = exclude_map.get(type_) if not only: f_set = fields and set(fields) e_set = exclude and set(exclude) self.field_set = field_set = set() self.relationship_set = relationship_set = set() for name in field_names: if should_include_field(self.inflect(name), include=f_set, exclude=e_set): field_set.add(name) for name in relationship_names: if should_include_field(self.inflect(name), include=f_set, exclude=e_set): relationship_set.add(name) only = list(field_set | {'id'}) for name in relationship_names: relationship = self._declared_fields[name] if (name in relationship_set or relationship.related_url or relationship.self_url): only.append(name) only.append('_url') self.field_order = list( chain(fields or [], map(self.inflect, field_names))) self.relationship_order = list( chain(fields or [], map(self.inflect, relationship_names))) only_set = set(only) kwargs['include_data'] = tuple( k for k in iterkeys(self.include_map) if k in only_set) super(JsonApiSerializer, self).__init__(only=only, **kwargs) self.instance = instance self.initial_data = data if storage: self.storage = storage elif isinstance(instance, Model): self.storage = instance.storage else: self.storage = None self.deleted = [] self.updated = [] @property def data(self): return self.dump(self.instance).data @cached_property def errors(self): if not hasattr(self, '_errors'): self.is_valid() return self._errors @cached_property def validated_data(self): if not hasattr(self, '_errors'): self.is_valid() return self._validated_data @cached_property def validated_profile_updates_data(self): if not hasattr(self, '_errors'): self.is_valid() return self._validated_profile_updates_data def deserialize_related_model(self, model, id_): if id_ is None: return None return model(self.storage, **{ model._pk_field: id_, }) def update(self, instance, validated_data): model = instance.__class__ errors = {} fields = [] for attrname in model._ordered_fields: if attrname in validated_data: try: value = validated_data[attrname] if attrname in model._field_names: setattr(instance, attrname, value) fields.append(attrname) elif attrname in model._relationship_names: # read in existing value to populate data stores getattr(instance, attrname) related_model = model._fields[attrname].model if isinstance(value, list): setattr(instance, attrname, [ self.deserialize_related_model(related_model, v) for v in value]) fields.append(attrname) else: setattr(instance, attrname, self.deserialize_related_model( related_model, value)) fields.append(attrname) except ValidationError as err: errors[attrname] = err.messages if errors: raise ValidationError(errors) instance.save(only=fields) return instance def create(self, validated_data): model = self.opts.model processed_attributes = { model._pk_field: AUTO_PK, } for attrname, value in iteritems(validated_data): if attrname in model._relationship_names: related_model = model._fields[attrname].model related_name = model._fields[attrname].related_name if isinstance(value, list): value = [self.deserialize_related_model(related_model, v) for v in value] else: value = self.deserialize_related_model(related_model, value) # read in existing values to populate data stores, for unique # key generation if value is not None: for v in (value if isinstance(value, list) else [value]): getattr(v, related_name) processed_attributes[attrname] = value instance = model(self.storage, **processed_attributes) instance.save() return instance def apply_profile_updates(self, validated_data, serializers): errors = {} for data, serializer in zip(validated_data, serializers): id_ = data['id'] instance = self.deserialize_related_model( serializer.opts.model, id_) serializer.instance = instance try: serializer.save() except ValidationError as err: errors.update(err.messages) continue self.updated.append(instance) self.updated.extend(serializer.updated) self.deleted.extend(serializer.deleted) if errors: raise ValidationError(errors) def save(self): if not hasattr(self, '_errors'): self.is_valid(raise_exception=True) validated_data = self.validated_data validated_profile_updates_data = self.validated_profile_updates_data errors = {} try: if self.instance is not None: self.instance = self.update(self.instance, validated_data) else: self.instance = self.create(validated_data) except ValidationError as err: errors.update(err.messages) if validated_profile_updates_data: try: self.apply_profile_updates(validated_profile_updates_data, self._profile_updates_serializers) except ValidationError as err: errors.update(err.messages) if errors: formatted_messages = self.format_errors(errors, many=self.many) raise ValidationError(formatted_messages) return self.instance def delete(self): data, serializers = self.load_profile_updates() self._validated_profile_updates_data = data self._profile_updates_serializers = serializers if self._validated_profile_updates_data: self.apply_profile_updates(self._validated_profile_updates_data, self._profile_updates_serializers) self.deleted.extend(self.instance.delete()) self.instance = self.instance.with_snapshots(('working',)) def is_valid(self, raise_exception=False): errors = [] try: self._validated_data = self.load(self.initial_data).data except (ValidationError, IncorrectTypeError) as err: errors.extend(err.messages.get('errors', [])) try: data, serializers = self.load_profile_updates() self._validated_profile_updates_data = data self._profile_updates_serializers = serializers except (ValidationError, IncorrectTypeError) as err: errors.extend(err.messages.get('errors', [])) if errors: self._validated_data = {} self._validated_profile_updates_data = [] self._errors = errors if raise_exception: err = ValidationError(u'Invalid data.') err.messages = { 'errors': errors } raise err return False self._errors = {} return True def load_profile_updates(self): if UPDATES_PROFILE not in self.initial_data.get( 'links', {}).get('profile', []): return [], [] for alias, profile in iteritems(self.initial_data.get('aliases', {})): if profile == UPDATES_PROFILE: break else: return [], [] errors = [] validated_data = [] profile_serializers = [] for i, update in enumerate( self.initial_data.get('meta', {}).get(alias, [])): if 'type' not in update: errors.append({ 'detail': '`data` object must include `type` key.', 'source': { 'pointer': '/meta/{}/{}/data'.format(alias, i) } }) continue type_ = update['type'] data = { 'data': update, } try: serializer_class = get_schema(type_) except ImproperlyConfigured: errors.append({ 'detail': 'Invalid type: {}.'.format(type_), 'source': { 'pointer': '/meta/{}/{}/data/type'.format(alias, i), }, }) continue serializer = serializer_class( data=data, partial=set( serializer_class.opts.model._ordered_fields).difference( {'id'})) try: validated_data.append(serializer.validated_data) profile_serializers.append(serializer) except (ValidationError, IncorrectTypeError) as err: errors.extend({ 'detail': error['detail'], 'source': { 'pointer': '/meta/{}/{}{}'.format( alias, i, error['source']['pointer']) }, } for error in err.messages.get('errors', [])) continue if errors: err = ValidationError(u'Invalid data for updates.') err.messages = { 'errors': errors } raise err return validated_data, profile_serializers @pre_dump(pass_many=True) def sort_collection(self, models, many): ordering = self.ordering if not many or not ordering: return models for key in reversed(ordering): reverse = key[0] == '-' if reverse: key = key[1:] models = sorted(models, key=partial(deep_getattr, key=key), reverse=reverse) return models @post_dump(pass_many=True) def format_json_api_response(self, data, many): updated_set = set() deleted_set = set() updated = [] deleted = [] for instance in self.deleted: if instance.data_key in deleted_set: continue deleted_set.add(instance.data_key) if instance != self.instance: deleted.append(instance) for instance in self.updated: if (instance.data_key in updated_set or instance.data_key in deleted_set): continue updated_set.add(instance.data_key) updated.append(instance) self.add_includes(updated) response = super(JsonApiSerializer, self).format_json_api_response( data, many) if 'included' in response: response['included'].sort(key=itemgetter('type', 'id')) deleted = self.format_profile_references(deleted) if deleted: self.add_profile_to_response(DELETED_PROFILE, DELETED_PROFILE_ALIAS, deleted, response) updated = self.format_profile_references(updated) if updated: self.add_profile_to_response(UPDATES_PROFILE, UPDATES_PROFILE_ALIAS, updated, response) if (isinstance(self.instance, Model) and self.instance.data_key in deleted_set): response.pop('data', None) if not response.get('meta'): return {} return order_dict(response, TOP_LEVEL_OBJECT_ORDER) def format_item(self, item): item = super(JsonApiSerializer, self).format_item(item) if 'attributes' in item: attributes = item.pop('attributes') attributes.pop('-url', None) # super call adds this if attributes: item['attributes'] = order_dict(attributes, self.field_order) if 'relationships' in item: item['relationships'] = order_dict(item['relationships'], self.relationship_order) return order_dict(item, RESOURCE_OBJECT_ORDER) def get_top_level_links(self, data, many): if self.current_url: return OrderedDict([('self', self.current_url)]) return None def get_resource_links(self, item): url = item.get('_url') if url: return OrderedDict([('self', url)]) return None def get_url(self, obj): return self.opts.url.format(self=obj) def add_includes(self, includes): included_data = self.included_data for instance in includes: type_ = type_from_model_name(instance.__class__.__name__) serializer = get_schema(type_)( instance, fields_map=self.fields_map, exclude_map=self.exclude_map) data = serializer.data item = data['data'] included_data[(item['type'], item['id'])] = item included_data.update(serializer.included_data) def format_profile_references(self, instances): references = [] for instance in instances: type_ = type_from_model_name(instance.__class__.__name__) serializer = get_schema(type_)( instance.with_snapshots(('working',)), only=('id',)) data = serializer.data.get('data', {}) if data: references.append(data) return references def add_profile_to_response(self, profile, alias, data, response): response.setdefault('aliases', {})[alias] = profile response.setdefault('links', {}).setdefault('profile', []).append( profile) response.setdefault('meta', {})[alias] = data class JsonApiPolymorphicSerializer(object): def __new__(cls, base, default_model, instance=None, data=None, many=False, **kwargs): if not many: # in the single instance case return the correct serializer by type # or the default_model's serializer if type is not valid for base type_ = None if instance: type_ = type_from_model_name(instance.__class__.__name__) elif data: type_ = data.get('data', {}).get('type') if type_: serializer_class = get_schema(type_) if not issubclass(serializer_class.opts.model, base): type_ = None if not type_: type_ = type_from_model_name(default_model.__name__) serializer_class = get_schema(type_) return serializer_class( instance=instance, data=data, many=many, **kwargs) if data: raise ValueError( u"You can only use a JsonApiPolymorphicSerializer with " u"many=True for serializing a ModelCollection") return super(JsonApiPolymorphicSerializer, cls).__new__( cls, base, default_model, instance, data, many, **kwargs) def __init__(self, base, default_model, instance=None, data=None, many=False, **kwargs): # this is only used for serializing a ModelCollection self.base = base self.default_model = default_model self.collection = instance self.kwargs = kwargs @property def data(self): links = None data = [] included = [] included_set = set() default_type = type_from_model_name(self.default_model.__name__) default_serializer = get_schema(default_type) for instance in self.collection: type_ = type_from_model_name(instance.__class__.__name__) serializer_class = get_schema(type_) if not issubclass(serializer_class.opts.model, self.base): serializer_class = default_serializer serialized = serializer_class(instance=instance, **self.kwargs).data if not links and 'links' in serialized: links = serialized['links'] data.append(serialized['data']) for include in serialized.get('included', []): key = (include['type'], include['id']) if key not in included_set: included.append(include) included_set.add(key) response = { 'data': data } if links: response['links'] = links if included: included.sort(key=itemgetter('type', 'id')) response['included'] = included return order_dict(response, TOP_LEVEL_OBJECT_ORDER) ================================================ FILE: portia_server/portia_api/jsonapi/utils.py ================================================ from collections import defaultdict, OrderedDict from django.utils.text import camel_case_to_spaces from requests.status_codes import _codes as status_codes from six import iteritems from six.moves import reduce from portia_orm.utils import cached_property, cached_property_ignore_set __all__ = [ 'cached_property', 'cached_property_ignore_set', 'dasherize', 'deep_getattr', 'order_dict', 'should_include_field', 'type_from_model_name', 'LINKS_OBJECT_ORDER', 'RESOURCE_OBJECT_ORDER', 'TOP_LEVEL_OBJECT_ORDER', ] TOP_LEVEL_OBJECT_ORDER = ( 'jsonapi', 'aliases', 'links', 'data', 'errors', 'included', 'meta', ) RESOURCE_OBJECT_ORDER = ( 'type', 'id', 'links', 'attributes', 'relationships', 'meta', ) LINKS_OBJECT_ORDER = ( 'self', 'related', 'profile', ) def camel_case_to_dashes(value): return '-'.join(camel_case_to_spaces(value).split(' ')) def dasherize(value): return str(value).replace('_', '-') def type_from_model_name(value): return '{}s'.format(camel_case_to_dashes(value)) def deep_getattr(obj, key): try: return reduce(getattr, key.split('.'), obj) except AttributeError: return None def should_include_field(field, include, exclude): if include is not None: return field in include if exclude is not None: return field not in exclude return True def order_dict(data, ordered_keys, key_map_cache={}): can_cache = True try: key_map = key_map_cache.get(ordered_keys) except TypeError: key_map = None can_cache = False if key_map is None: key_map = defaultdict(lambda: float('inf')) for i, k in enumerate(ordered_keys): if k not in key_map: key_map[k] = i if can_cache: key_map_cache[ordered_keys] = key_map return OrderedDict(sorted(iteritems(data), key=lambda kv: key_map[kv[0]])) def get_status_title(status_code): return status_codes[status_code][0].replace('_', ' ').title() ================================================ FILE: portia_server/portia_api/resources/__init__.py ================================================ ================================================ FILE: portia_server/portia_api/resources/annotations.py ================================================ from .projects import BaseProjectModelRoute from ..jsonapi.utils import cached_property from portia_orm.models import BaseAnnotation, Annotation class AnnotationRoute(BaseProjectModelRoute): lookup_url_kwarg = 'annotation_id' default_model = Annotation polymorphic = BaseAnnotation @cached_property def sample(self): return (self.project.spiders[self.kwargs.get('spider_id')] .samples[self.kwargs.get('sample_id')]) def perform_create(self, serializer): self.sample.ordered_children # preload items and annotations return super(AnnotationRoute, self).perform_create(serializer) def get_instance(self): return self.get_collection()[self.kwargs.get('annotation_id')] def get_collection(self): project = self.project project.schemas # preload schemas and fields project.extractors # preload extractors return self.sample.ordered_children def get_detail_kwargs(self): return { 'include_data_map': { 'items': [ 'schema.fields', 'annotations', ], 'annotations': [ 'field.schema.fields', 'extractors', ], }, } ================================================ FILE: portia_server/portia_api/resources/extractors.py ================================================ from .projects import BaseProjectModelRoute from portia_orm.models import Extractor class ExtractorRoute(BaseProjectModelRoute): lookup_url_kwarg = 'extractor_id' default_model = Extractor def get_instance(self): return self.get_collection()[self.kwargs.get('extractor_id')] def get_collection(self): return self.project.extractors ================================================ FILE: portia_server/portia_api/resources/fields.py ================================================ from portia_orm.models import Field from .projects import BaseProjectModelRoute from ..jsonapi.exceptions import JsonApiBadRequestError class FieldRoute(BaseProjectModelRoute): lookup_url_kwarg = 'field_id' default_model = Field def perform_create(self, serializer): self.project.schemas # preload schemas super(FieldRoute, self).perform_create(serializer) def get_instance(self): return self.get_collection()[self.kwargs.get('field_id')] def get_collection(self): return self.project.schemas[self.kwargs.get('schema_id')].fields def destroy(self, *args, **kwargs): annotation_count = self._annotation_count if annotation_count > 0: raise JsonApiBadRequestError(self._destroy_error(annotation_count)) return super(FieldRoute, self).destroy(*args, **kwargs) def _destroy_error(self, annotation_count): field = self.get_instance() annotation = 'annotation' if annotation_count == 1 else 'annotations' return ('Unable to delete the field "{}" as it has {} {}.' .format(field.name, annotation_count, annotation)) @property def _annotation_count(self): self._load_annotations() return len(self.get_instance().annotations) def _load_annotations(self): for spider in self.project.spiders: for sample in spider.samples: sample.annotations ================================================ FILE: portia_server/portia_api/resources/items.py ================================================ from .projects import BaseProjectModelRoute from ..jsonapi.utils import cached_property from portia_orm.models import Item class ItemRoute(BaseProjectModelRoute): lookup_url_kwarg = 'item_id' default_model = Item @cached_property def spider(self): return self.project.spiders[self.kwargs.get('spider_id')] def perform_create(self, serializer): self.spider.samples # preload samples return super(ItemRoute, self).perform_create(serializer) def get_instance(self): return self.get_collection()[self.kwargs.get('item_id')] def get_collection(self): project = self.project project.schemas # preload schemas and fields project.extractors # preload extractors return self.spider.samples[self.kwargs.get('sample_id')].ordered_items def get_detail_kwargs(self): return { 'include_data_map': { 'items': [ 'schema.fields', 'annotations', ], 'annotations': [ 'field.schema.fields', 'extractors', ], }, } ================================================ FILE: portia_server/portia_api/resources/models.py ================================================ from itertools import chain from marshmallow_jsonapi import Schema, fields from marshmallow import pre_dump, post_load class SlydSchema(Schema): _properties = ('project', 'spider', 'schema', 'item', 'sample', 'field') @staticmethod def empty_data(): return { 'meta': {} } def __init__(self, *args, **kwargs): self._skip_relationships = kwargs.pop('skip_relationships', False) if self._skip_relationships: relationships = ((f, '%s_id' % f) for f in self._properties) exclude = kwargs.get('exclude', []) excluded = tuple(chain(exclude, *zip(*relationships))) kwargs['exclude'] = excluded super(SlydSchema, self).__init__(*args, **kwargs) @property def project_id(self): return self.context.get('project_id') @property def spider_id(self): return self.context.get('spider_id') @property def sample_id(self): return self.context.get('sample_id') @property def schema_id(self): return self.context.get('schema_id') @property def item_id(self): return self.context.get('item_id') @property def field_id(self): return self.context.get('field_id') @pre_dump def _dump_relationship_properties(self, item): if getattr(self, '_skip_relationships', False): return item for attr in self._properties: _id = '_'.join((attr, 'id')) if _id not in item or item['id'] is None: item[_id] = getattr(self, _id) else: self.context[_id] = item[_id] if item.get(attr) is None and item[_id]: item[attr] = {'id': item[_id]} return item class ProjectSchema(SlydSchema): id = fields.Str(load_from='name') name = fields.Str() spiders = fields.Relationship( related_url='/api/projects/{project_id}/spiders', related_url_kwargs={'project_id': ''}, type_='spiders', include_resource_linkage=True, many=True ) schemas = fields.Relationship( related_url='/api/projects/{project_id}/schemas', related_url_kwargs={'project_id': ''}, type_='schemas', include_resource_linkage=True, many=True ) extractors = fields.Relationship( related_url='/api/projects/{project_id}/extractors', related_url_kwargs={'project_id': ''}, type_='extractors', include_resource_linkage=True, many=True ) project = fields.Relationship( self_url='/api/projects/{project_id}', self_url_kwargs={'project_id': ''}, type_='projects' ) class Meta: type_ = 'projects' class SchemaSchema(SlydSchema): id = fields.Str(dump_only=True) name = fields.Str() default = fields.Boolean() project = fields.Relationship( related_url='/api/projects/{project_id}', related_url_kwargs={'project_id': ''}, type_='projects', include_resource_linkage=True ) fields = fields.Relationship( related_url='/api/projects/{project_id}/schemas/{schema_id}/fields', related_url_kwargs={'project_id': '', 'schema_id': ''}, many=True, include_resource_linkage=True, type_='fields' ) class Meta: type_ = 'schemas' class FieldSchema(SlydSchema): id = fields.Str() name = fields.Str() type = fields.Str() vary = fields.Boolean(default=False) required = fields.Boolean(default=False) project = fields.Relationship( related_url='/api/projects/{project_id}', related_url_kwargs={'project_id': ''}, type_='projects', include_resource_linkage=True ) schema = fields.Relationship( related_url='/api/projects/{project_id}/schemas/{schema_id}', related_url_kwargs={'project_id': '', 'schema_id': ''}, type_='schema', include_resource_linkage=True ) class Meta: type_ = 'fields' class SpiderSchema(SlydSchema): id = fields.Str(dump_only=True, load_from='name') name = fields.Str() start_urls = fields.List(fields.Str(), default=[]) links_to_follow = fields.Str(default='patterns') follow_patterns = fields.List(fields.Str(), default=[]) exclude_patterns = fields.List(fields.Str(), default=[]) js_enabled = fields.Boolean(default=False) js_enable_patterns = fields.List(fields.Str(), default=[]) js_disable_patterns = fields.List(fields.Str(), default=[]) respect_nofollow = fields.Boolean(default=True) allowed_domains = fields.List(fields.Str(), default=[]) login_url = fields.Str() login_user = fields.Str() login_password = fields.Str() perform_login = fields.Boolean(default=False) samples = fields.Relationship( related_url='/api/projects/{project_id}/spider/{spider_id}/samples', related_url_kwargs={'project_id': '', 'spider_id': ''}, many=True, include_resource_linkage=True, type_='samples' ) project = fields.Relationship( related_url='/api/projects/{project_id}', related_url_kwargs={'project_id': ''}, type_='projects', include_resource_linkage=True ) @pre_dump def _dump_login_data(self, item): init_requests = item.pop('init_requests', None) if init_requests: login_request = init_requests[0] item['login_url'] = login_request['loginurl'] item['login_user'] = login_request['username'] item['login_password'] = login_request['password'] return item @post_load def _load_login_data(self, item): fields = ('login_url', 'login_user', 'login_password') if all(field in item and item[field] for field in fields): item['init_requests'] = [{ 'type': 'login', 'loginurl': item.pop('login_url'), 'username': item.pop('login_user'), 'password': item.pop('login_password') }] for field in fields: item.pop(field, None) return item class Meta: type_ = 'spiders' class SampleSchema(SlydSchema): id = fields.Str(dump_only=True) name = fields.Str() url = fields.Str(required=True) page_id = fields.Str() page_type = fields.Str(default='item') scrapes = fields.Str() extractors = fields.Dict(default={}) project = fields.Relationship( related_url='/api/projects/{project_id}', related_url_kwargs={'project_id': ''}, type_='projects', include_resource_linkage=True ) spider = fields.Relationship( related_url='/api/projects/{project_id}/spiders/{spider_id}', related_url_kwargs={'project_id': '', 'spider_id': ''}, type_='spiders', include_resource_linkage=True ) original_body = fields.Relationship( related_url='/api/projects/{project_id}/spider/{spider_id}/samples/' '{sample_id}/original_body', related_url_kwargs={'project_id': '', 'spider_id': '', 'sample_id': ''}, type_='html', include_resource_linkage=False ) rendered_body = fields.Relationship( related_url='/api/projects/{project_id}/spider/{spider_id}/samples/' '{sample_id}/rendered_body', related_url_kwargs={'project_id': '', 'spider_id': '', 'sample_id': ''}, type_='html', include_resource_linkage=False ) items = fields.Relationship( related_url='/api/projects/{project_id}/spider/{spider_id}/samples/' '{sample_id}/items', related_url_kwargs={'project_id': '', 'spider_id': '', 'sample_id': ''}, type_='items', many=True, include_resource_linkage=True ) def dump(self, obj, many=None, update_fields=True, **kwargs): many = self.many if many is None else bool(many) if many: for o in obj: o.setdefault('items', []) else: obj.setdefault('items', []) return super(SampleSchema, self).dump(obj, many, update_fields, **kwargs) class Meta: type_ = 'samples' class BaseAnnotationSchema(SlydSchema): id = fields.Str() attribute = fields.Str(required=True) accept_selectors = fields.List(fields.Str(), default=[]) reject_selectors = fields.List(fields.Str(), default=[]) tagid = fields.Integer(required=True) text_content = fields.Str() selector = fields.Str() sample = fields.Relationship( related_url='/api/projects/{project_id}/spiders/{spider_id}/samples/' '{sample_id}', related_url_kwargs={'project_id': '', 'spider_id': '', 'sample_id': ''}, type_='samples', include_resource_linkage=True ) parent = fields.Relationship( related_url_kwargs={'project_id': '', 'spider_id': '', 'sample_id': '', 'item_id': ''}, type_='items', include_resource_linkage=True ) @property def parent_id(self): return self.context.get('container_id', self.item_id) @pre_dump def _dump_parent_id(self, item): parent_id = None if 'parent' in item: parent_id = item['parent']['id'] if not parent_id: parent_id = item.get('container_id', self.parent_id) or '' if (item['id'].split('#')[0] == parent_id or parent_id.split('#')[0] == item['id']): item.pop('parent', None) item.pop('parent_id', None) return if parent_id: item['parent'] = {'id': parent_id} if parent_id and item.get('parent_id') is None: item['parent_id'] = parent_id class AnnotationSchema(BaseAnnotationSchema): required = fields.Boolean(default=False) ignore = fields.Boolean(default=False) ignore_beneath = fields.Boolean(default=False) variant = fields.Integer(default=False) slice = fields.List(fields.Integer()) pre_text = fields.Str() post_text = fields.Str() selection_mode = fields.Str() field = fields.Relationship( related_url='/api/projects/{project_id}/schemas/{schema_id}/fields/' '{field_id}', related_url_kwargs={'project_id': '', 'schema_id': '', 'field_id': ''}, type_='fields', include_resource_linkage=True ) extractors = fields.Relationship( related_url='/api/projects/{project_id}/extractors', related_url_kwargs={'project_id': ''}, many=True, include_resource_linkage=True, type_='extractors' ) class Meta: type_ = 'annotations' class ItemAnnotationSchema(BaseAnnotationSchema): item_container = fields.Boolean(default=True) container_id = fields.Str() repeated = fields.Boolean() repeated_container_id = fields.Str(dump_only=True) repeated_accept_selectors = fields.Str(dump_only=True) siblings = fields.Integer() parent_field = fields.Str() schema = fields.Relationship( related_url='/api/projects/{project_id}/schemas/{schema_id}', related_url_kwargs={'project_id': '', 'schema_id': ''}, type_='schemas', include_resource_linkage=True ) class Meta: type_ = 'item_annotations' class ExtractorSchema(SlydSchema): id = fields.Str() type = fields.Str() value = fields.Str() project = fields.Relationship( related_url='/api/projects/{project_id}', related_url_kwargs={'project_id': ''}, type_='projects', include_resource_linkage=True ) @pre_dump def _dump_extractor_attributes(self, item): if 'type' not in item: item['type'] = 'type' if 'type_extractor' in item else 'regex' if 'value' not in item: item['value'] = item['type_extractor'] if item['type'] == 'type' \ else item['regular_expression'] return item class Meta: type_ = 'extractors' class HtmlSchema(SlydSchema): id = fields.Str() html = fields.Str() class Meta: type_ = 'html' class RenderedBody(SlydSchema): id = fields.Str() html = fields.Str() class Meta: type_ = 'rendered-bodys' class OriginalBody(SlydSchema): id = fields.Str() html = fields.Str() class Meta: type_ = 'original-bodys' class ItemSchema(SlydSchema): """Instance of a schema. Meta item built from sample.""" id = fields.Str() sample = fields.Relationship( related_url='/api/projects/{project_id}/spider/{spider_id}/samples/' '{sample_id}', related_url_kwargs={'project_id': '', 'spider_id': '', 'sample_id': ''}, include_resource_linkage=True, type_='samples' ) schema = fields.Relationship( related_url='/api/projects/{project_id}/schemas/{schema_id}', related_url_kwargs={'project_id': '', 'schema_id': ''}, type_='schemas', include_resource_linkage=True ) annotations = fields.Relationship( related_url='/api/projects/{project_id}/spider/{spider_id}/samples/' '{sample_id}/items/{item_id}/annotations', related_url_kwargs={'project_id': '', 'spider_id': '', 'sample_id': '', 'item_id': ''}, many=True, include_resource_linkage=True, type_='annotations' ) item_annotation = fields.Relationship( related_url='/api/projects/{project_id}/spider/{spider_id}/samples/' '{sample_id}/items/{item_id}/item_annotation', related_url_kwargs={'project_id': '', 'spider_id': '', 'sample_id': '', 'item_id': ''}, include_resource_linkage=True, type_='item_annotations' ) parent = fields.Relationship(type_='items', include_resource_linkage=True) @pre_dump def _dump_parent_id(self, item): parent_id = item.get('container_id') or '' if parent_id: item['parent'] = {'id': parent_id} if parent_id and item.get('parent_id') is None: item['parent_id'] = parent_id class Meta: type_ = 'items' ================================================ FILE: portia_server/portia_api/resources/projects.py ================================================ from collections import OrderedDict from django.conf import settings from django.utils.functional import cached_property from dulwich.objects import Commit from rest_framework.decorators import detail_route from rest_framework.response import Response from rest_framework.status import HTTP_200_OK, HTTP_201_CREATED from six import iteritems from scrapy.utils.misc import load_object from portia_orm.models import Project from storage import get_storage_class from storage.backends import InvalidFilename from .route import (JsonApiRoute, JsonApiModelRoute, CreateModelMixin, ListModelMixin, RetrieveModelMixin) from .response import FileResponse from ..jsonapi.exceptions import (JsonApiFeatureNotAvailableError, JsonApiBadRequestError, JsonApiNotFoundError, JsonApiConflictError) from ..utils.download import ProjectArchiver, CodeProjectArchiver from ..utils.copy import ModelCopier, MissingModelException Deployer = load_object(settings.PROJECT_DEPLOYER) class ProjectDownloadMixin(object): @detail_route(methods=['get']) def download(self, *args, **kwargs): fmt = self.query.get('format', 'spec') version = self.query.get('version', None) branch = self.query.get('branch', None) selector = self.query.get('selector') or 'css' spider_id = self.kwargs.get('spider_id', None) spiders = [spider_id] if spider_id is not None else None try: self.project except InvalidFilename as e: raise JsonApiNotFoundError(str(e)) if hasattr(self.storage, 'checkout') and (version or branch): try: if version and len(version) < 40: version = self.commit_from_short_sha(version).id self.storage.checkout(version, branch) except IOError: pass except ValueError as e: raise JsonApiNotFoundError(str(e)) archiver = CodeProjectArchiver if fmt == u'code' else ProjectArchiver try: content = archiver(self.storage).archive( spiders, selector=selector) except IOError as e: raise JsonApiNotFoundError(str(e)) try: name = u'{}.zip'.format(self.project.name) except UnicodeEncodeError: name = str(self.project.id) return FileResponse(name, content, status=HTTP_200_OK) def commit_from_short_sha(self, version): for oid in self.storage.repo._repo.object_store: if oid.startswith(version): obj = self.storage.repo._repo.get_object(oid) if isinstance(obj, Commit): return obj raise JsonApiNotFoundError( 'Could not find commit for `{}`'.format(version) ) class BaseProjectRoute(JsonApiRoute): @cached_property def projects(self): storage_class = get_storage_class() return storage_class.get_projects(self.request.user) @cached_property def project(self): project_id = self.kwargs.get('project_id') try: name = self.projects[project_id] return Project(self.storage, id=project_id, name=name) except KeyError: raise JsonApiNotFoundError() class BaseProjectModelRoute(BaseProjectRoute, JsonApiModelRoute): pass class ProjectRoute(ProjectDownloadMixin, BaseProjectRoute, ListModelMixin, RetrieveModelMixin, CreateModelMixin): lookup_url_kwarg = 'project_id' default_model = Project class FakeStorage(object): def exists(self, *args, **kwargs): return False def listdir(self, *args, **kwargs): return [], [] def create(self, request): """Create a new project from the provided attributes""" try: name = self.data['data']['attributes']['name'] except KeyError: raise JsonApiBadRequestError('No `name` provided') self.kwargs['project_id'] = name projects = self.projects if not self.storage.is_valid_filename(name) or '.' in name: raise JsonApiBadRequestError( '"{}" is not a valid project name,\nProject names may only ' 'contain letters and numbers'.format(name)) if name in projects: raise JsonApiBadRequestError( 'A project with the name "{}" already exists'.format(name)) # Bootstrap project storage = self.storage storage.commit() project = Project(storage, id=name, name=name) serializer = self.get_serializer(project, storage=storage) data = serializer.data headers = self.get_success_headers(data) return Response(data, status=HTTP_201_CREATED, headers=headers) # def update(self): # """Update an exiting project with the provided attributes""" # def destroy(self): # """Delete the requested project""" @detail_route(methods=['get']) def status(self, *args, **kwargs): response = self.retrieve() data = OrderedDict() data.update({ 'meta': { 'changes': self.get_project_changes() } }) data.update(response.data) return Response(data, status=HTTP_200_OK) @detail_route(methods=['put', 'patch', 'post']) def publish(self, *args, **kwargs): if not self.storage.version_control and hasattr(self.storage, 'repo'): raise JsonApiFeatureNotAvailableError() if not self.get_project_changes(): raise JsonApiBadRequestError('You have no changes to publish') force = self.query.get('force', False) branch = self.storage.branch published = self.storage.repo.publish_branch(branch, force=force) if not published: raise JsonApiConflictError( 'A conflict occurred when publishing your changes.' 'You must resolve the conflict before the project can be ' 'published.') self.deploy() self.storage.repo.delete_branch(branch) response = self.retrieve() return Response(response.data, status=HTTP_200_OK) @detail_route(methods=['POST']) def deploy(self, *args, **kwargs): data = self._deploy() return Response(data, HTTP_200_OK) @detail_route(methods=['put', 'patch', 'post']) def reset(self, *args, **kwargs): if not self.storage.version_control and hasattr(self.storage, 'repo'): raise JsonApiFeatureNotAvailableError() branch = self.storage.branch master = self.storage.repo.refs['refs/heads/master'] self.storage.repo.refs['refs/heads/%s' % branch] = master return self.retrieve() @detail_route(methods=['post']) def copy(self, *args, **kwargs): from_project_id = self.query.get('from') or self.data.get('from') if not from_project_id: raise JsonApiBadRequestError('`from` parameter must be provided.') try: self.projects[from_project_id] except KeyError: raise JsonApiNotFoundError( 'No project exists with the id "{}"'.format(from_project_id)) models = self.data.get('data', []) if not models: raise JsonApiBadRequestError('No models provided to copy.') try: copier = ModelCopier(self.project, self.storage, from_project_id) copier.copy(models) except MissingModelException as e: raise JsonApiBadRequestError( 'Could not find the following ids "{}" in the project.'.format( '", "'.join(e.args[0]))) response = self.retrieve() return Response(response.data, status=HTTP_201_CREATED) @detail_route(methods=['post']) def rollback(self, *args, **kwargs): if not self.storage.version_control and hasattr(self.storage, 'repo'): raise JsonApiFeatureNotAvailableError() version = self.query.get('version') branch = self.query.get('branch') if not (branch or version): raise JsonApiBadRequestError( 'Need either `branch` or `version` arguments to rollback to') if branch: commit = self.storage.repo.refs['refs/heads/{}'.format(branch)] else: commit = self.commit_from_short_sha(version).id self.storage.repo.refs['refs/heads/master'] = commit self.storage.commit() self.deploy() return self.retrieve() def get_instance(self): return self.project def get_collection(self): storage = self.FakeStorage() return Project.collection( Project(storage, id=project_id, name=name) for project_id, name in iteritems(self.projects)) def get_detail_kwargs(self): return { 'include_data': [ 'spiders', 'schemas', ], 'fields_map': { 'spiders': [ 'project', ], 'schemas': [ 'name', 'default', 'project', ], }, 'exclude_map': { 'projects': [ 'extractors', ], } } def get_list_kwargs(self): return { 'fields_map': { 'projects': [ 'name', ], } } def get_project_changes(self): storage = self.storage if not storage.version_control: raise JsonApiFeatureNotAvailableError() return [{'type': type_, 'path': path, 'old_path': old_path} for type_, path, old_path in storage.changed_files()] def _deploy(self): if settings.CAPABILITIES.get('deploy_projects'): return Deployer(self.project).deploy() ================================================ FILE: portia_server/portia_api/resources/response.py ================================================ import json from django.http.response import HttpResponse from wsgiref.util import FileWrapper from six.moves import map from twisted.python.compat import intToBytes class BaseApiResource(object): def render(self, request): raise NotImplementedError def render_async(self, request): body = self.render(request) if body is not NOT_DONE_YET: if body is not None: request.setHeader(b'content-length', intToBytes(len(body))) request.write(body) request.finish() class JsonApiResource(BaseApiResource): def __init__(self, status, data=None): self.status = status self.data = data def render(self, request): request.setResponseCode(self.status) data = self.data if data is not None: content_type = b"application/vnd.api+json" profiles = data.get('links', {}).get('profile', []) if profiles: content_type += b'; profile="{}"'.format( b' '.join(map(bytes, profiles))) request.setHeader(b'content-type', content_type) return json.dumps(data, indent=2) class FileResponse(HttpResponse): def __init__(self, name, content, *args, **kwargs): content = FileWrapper(content) super(FileResponse, self).__init__( content=content, content_type='application/zip') self['Content-Disposition'] = 'attachment; filename="%s"' % name ================================================ FILE: portia_server/portia_api/resources/route.py ================================================ from collections import Sequence from operator import attrgetter from django.db import transaction from django.http.response import Http404 from django.utils.functional import cached_property from marshmallow import ValidationError from marshmallow_jsonapi.exceptions import IncorrectTypeError from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.status import (HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT) from rest_framework.viewsets import ViewSet from portia_orm.collection import ModelCollection from portia_orm.exceptions import ProtectedError from portia_orm.relationships import BelongsTo, HasMany from storage import create_project_storage from ..jsonapi.exceptions import (JsonApiBadRequestError, JsonApiConflictError, JsonApiValidationError, render_exception) from ..jsonapi.parsers import JSONApiParser, JSONParser from ..jsonapi.registry import get_schema from ..jsonapi.renderers import JSONApiRenderer, JSONRenderer from ..jsonapi.serializers import JsonApiPolymorphicSerializer from ..jsonapi.utils import type_from_model_name class JsonApiRoute(ViewSet): default_model = None polymorphic = None permission_classes = (IsAuthenticated,) parser_classes = (JSONApiParser, JSONParser) renderer_classes = (JSONApiRenderer, JSONRenderer) def __str__(self): return '{} {}'.format(self.method.upper(), self.path) def __repr__(self): return 'Route(%s)' % str(self) @cached_property def method(self): return self.request.method.lower() @cached_property def path(self): return self.request.path @cached_property def query(self): return self.request.query_params or {} @cached_property def data(self): return self.request.data or {} @cached_property def user(self): return self.request.user @cached_property def storage(self): if 'project_id' in self.kwargs: return create_project_storage( self.kwargs['project_id'], author=self.user) return None @transaction.atomic def dispatch(self, request, *args, **kwargs): return super(JsonApiRoute, self).dispatch(request, *args, **kwargs) def handle_exception(self, exc): response = super(JsonApiRoute, self).handle_exception(exc) if isinstance(exc, Http404): response.data['detail'] = "Resource '%s' not found." % self.path status_code = response.status_code if (isinstance(response.data, dict) and len(response.data) == 1 and 'detail' in response.data): response.data = render_exception(status_code, response.data['detail']) return response def get_instance(self): raise NotImplementedError def get_collection(self): raise NotImplementedError def filter_collection(self, collection): if 'filter[id]' in self.query: if not isinstance(collection, ModelCollection): raise JsonApiBadRequestError(u"Cannot filter this collection.") ids = [] for id_list in self.query.getlist('filter[id]'): ids.extend(id_list.split(',')) collection = collection.__class__((collection[id_] for id_ in ids)) for key in self.query.keys(): if (key != 'filter[id]' and key.startswith('filter[') and key[-1] == ']'): field_name = key[7:-1] field_values = set() for field_list in self.query.getlist(key): field_values.update(field_list.split(',')) filtered = [] for obj in collection: try: field = obj._fields[field_name] if isinstance(field, BelongsTo): related = getattr(obj, field_name) filter_values = {related.pk if related else 'null'} elif isinstance(field, HasMany): filter_values = {attrgetter('pk')(f) for f in getattr(obj, field_name)} else: value = getattr(obj, field_name) if isinstance(value, Sequence): filter_values = set(value) else: filter_values = {value} if filter_values.intersection(field_values): filtered.append(obj) except (AttributeError, KeyError, TypeError): # skip objects which don't have a field pass collection = collection.__class__(filtered) return collection def get_serializer(self, instance=None, data=None, many=False, **kwargs): params = {} if self.method == 'get': params.update({ 'current_url': self.path, }) if many: params.update(self.get_list_kwargs()) else: params.update(self.get_detail_kwargs()) params.update(self.get_request_kwargs()) params.update(kwargs) if self.polymorphic: return JsonApiPolymorphicSerializer( base=self.polymorphic, default_model=self.default_model, instance=instance, data=data, many=many, **params) type_ = type_from_model_name(self.default_model.__name__) return get_schema(type_)( instance=instance, data=data, many=many, **params) def get_detail_kwargs(self): return {} def get_list_kwargs(self): return self.get_detail_kwargs() def get_request_kwargs(self): kwargs = {} if 'include' in self.query: include = [] for include_list in self.query.getlist('include'): include.extend(include_list.split(',')) kwargs['include_data'] = include fields = {} for key in self.query.keys(): if key.startswith('fields[') and key[-1] == ']': field = key[7:-1] for field_list in self.query.getlist(key): if field in fields: fields[field].extend(field_list.split(',')) else: fields[field] = field_list.split(',') kwargs['fields_map'] = fields if 'sort' in self.query: sort_ = [] for sort_list in self.query.getlist('sort'): sort_.extend(sort_list.split(',')) kwargs['ordering'] = sort_ return kwargs class CreateModelMixin(object): def create(self, *args, **kwargs): serializer = self.get_serializer(data=self.data, storage=self.storage, partial={'id'}) try: self.perform_create(serializer) except ValidationError as err: raise JsonApiValidationError(err.messages) data = serializer.data self.storage.commit() headers = self.get_success_headers(data) return Response(data, status=HTTP_201_CREATED, headers=headers) def perform_create(self, serializer): serializer.save() def get_success_headers(self, data): try: return { 'Location': data['data']['links']['self'] } except (TypeError, KeyError): return {} class ListModelMixin(object): def list(self, *args, **kwargs): try: collection = self.filter_collection(self.get_collection()) except (TypeError, IndexError, KeyError): raise Http404 serializer = self.get_serializer(collection, many=True) return Response(serializer.data, status=HTTP_200_OK) class RetrieveModelMixin(object): def retrieve(self, *args, **kwargs): try: instance = self.get_instance() except (TypeError, IndexError, KeyError): raise Http404 serializer = self.get_serializer(instance) return Response(serializer.data, status=HTTP_200_OK) class UpdateModelMixin(object): def update(self, *args, **kwargs): try: instance = self.get_instance() except (TypeError, IndexError, KeyError): raise Http404 if kwargs.pop('partial', False): partial = set(instance.__class__._ordered_fields) - {'id'} else: partial = False serializer = self.get_serializer( instance, data=self.data, partial=partial) try: self.perform_update(serializer) except (ValidationError, IncorrectTypeError) as err: raise JsonApiValidationError(err.messages) data = serializer.data self.storage.commit() return Response(data, status=HTTP_200_OK) def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return self.update(request, *args, **kwargs) def perform_update(self, serializer): serializer.save() class DestroyModelMixin(object): def destroy(self, *args, **kwargs): try: instance = self.get_instance() except (TypeError, IndexError, KeyError): raise Http404 serializer = self.get_serializer(instance, data=self.data) try: self.perform_destroy(serializer) except (ValidationError, IncorrectTypeError) as err: raise JsonApiValidationError(err.messages) except ProtectedError: raise JsonApiConflictError(u"You cannot delete this resource.") data = serializer.data self.storage.commit() if data: return Response(data, status=HTTP_200_OK) return Response(status=HTTP_204_NO_CONTENT) def perform_destroy(self, serializer): return serializer.delete() class JsonApiModelRoute(JsonApiRoute, ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin): pass ================================================ FILE: portia_server/portia_api/resources/samples.py ================================================ from .projects import BaseProjectModelRoute from .serializers import SampleSerializer from portia_orm.models import Sample class SampleRoute(BaseProjectModelRoute): lookup_url_kwarg = 'sample_id' default_model = Sample def perform_create(self, serializer): self.project.spiders # preload spiders super(SampleRoute, self).perform_create(serializer) def get_instance(self): return self.get_collection()[self.kwargs.get('sample_id')] def get_collection(self): project = self.project project.schemas # preload schemas and fields project.extractors # preload extractors spider = project.spiders[self.kwargs.get('spider_id')] for sample in spider.samples: sample = sample.load(sample.storage, sample) sample.url spider.samples.add(sample) return spider.samples def get_detail_kwargs(self): return { 'include_data': [ 'items', ], 'include_data_map': { 'items': [ 'schema.fields', 'annotations', ], 'annotations': [ 'field.schema.fields', 'extractors', ], }, } def get_list_kwargs(self): excludes = (SampleSerializer.opts .default_kwargs['exclude_map']['samples']) return { 'exclude_map': { 'samples': excludes + [ 'items', ] } } ================================================ FILE: portia_server/portia_api/resources/schemas.py ================================================ from portia_orm.models import Schema from .projects import BaseProjectModelRoute from ..jsonapi.exceptions import JsonApiBadRequestError, JsonApiNotFoundError class SchemaRoute(BaseProjectModelRoute): lookup_url_kwarg = 'schema_id' default_model = Schema def get_instance(self): return self.get_collection()[self.kwargs.get('schema_id')] def get_collection(self): return self.project.schemas def get_list_kwargs(self): return { 'fields_map': { 'schemas': [ 'name', 'default', 'project', ], } } def update(self, *args, **kwargs): # Reset default schema if current schema will be default if self.data.get('data', {}).get('attributes', {}).get('default'): for schema in self.get_collection(): if schema.default: schema.default = False schema.save() return super(SchemaRoute, self).update(*args, **kwargs) def destroy(self, *args, **kwargs): try: schema = self.get_instance() except KeyError: raise JsonApiNotFoundError('Unable to find the requested schema') for spider in self.project.spiders: for sample in spider.samples: for item in sample.items: if self._item_uses_schema(item): raise JsonApiBadRequestError( 'Unable to delete the data format "%s" as it is used ' "by a spider's sample." % schema.name) return super(SchemaRoute, self).destroy(*args, **kwargs) def _item_uses_schema(self, item): schema = self.get_instance() if item.schema.id == schema.id: return True for item in item.annotations: if hasattr(item, 'schema') and self._item_uses_schema(item): return True return False ================================================ FILE: portia_server/portia_api/resources/serializers.py ================================================ from operator import attrgetter from six.moves import map from portia_api.jsonapi.serializers import JsonApiSerializer from portia_orm.base import AUTO_PK from portia_orm.exceptions import ProtectedError from portia_orm.models import (Project, Schema, Field, Extractor, Spider, Sample, Item, Annotation, RenderedBody, OriginalBody) from portia_api.utils.projects import unique_name from portia_api.utils.annotations import choose_field_type def clear_auto_created(instance): if instance.auto_created: instance.auto_created = False instance.save(only=('auto_created',)) class SpiderListSerializer(JsonApiSerializer): class Meta: model = Spider url = '/api/projects/{self.project.id}/spiders/{self.id}' links = { 'project': { 'related': '/api/projects/{self.project.id}', }, } class ProjectSerializer(JsonApiSerializer): class Meta: model = Project url = '/api/projects/{self.id}' links = { 'spiders': { 'related': '/api/projects/{self.id}/spiders', 'serializer': SpiderListSerializer, }, 'schemas': { 'related': '/api/projects/{self.id}/schemas', }, 'extractors': { 'related': '/api/projects/{self.id}/extractors', }, } class SchemaSerializer(JsonApiSerializer): class Meta: model = Schema url = '/api/projects/{self.project.id}/schemas/{self.id}' links = { 'project': { 'related': '/api/projects/{self.project.id}', }, 'fields': { 'related': '/api/projects/{self.project.id}/schemas' '/{self.id}/fields', }, } default_kwargs = { 'include_data': [ 'fields', ], 'exclude_map': { 'schemas': [ 'auto-created', 'items', ] } } def update(self, instance, validated_data): instance = super(SchemaSerializer, self).update( instance, validated_data) clear_auto_created(instance) return instance class FieldSerializer(JsonApiSerializer): class Meta: model = Field url = ('/api/projects/{self.schema.project.id}/schemas' '/{self.schema.id}/fields/{self.id}') links = { 'schema': { 'related': '/api/projects/{self.schema.project.id}/schemas' '/{self.schema.id}', }, } default_kwargs = { 'exclude_map': { 'fields': [ 'auto-created', 'annotations', ] } } def create(self, validated_data): field = super(FieldSerializer, self).create(validated_data) clear_auto_created(field.schema) return field def update(self, instance, validated_data): instance = super(FieldSerializer, self).update(instance, validated_data) clear_auto_created(instance) clear_auto_created(instance.schema) return instance def delete(self): clear_auto_created(self.instance.schema) super(FieldSerializer, self).delete() class ExtractorSerializer(JsonApiSerializer): class Meta: model = Extractor url = '/api/projects/{self.project.id}/extractors/{self.id}' links = { 'project': { 'related': '/api/projects/{self.project.id}', }, } default_kwargs = { 'exclude_map': { 'extractors': [ 'annotations', ] } } class SpiderSerializer(JsonApiSerializer): class Meta: model = Spider url = '/api/projects/{self.project.id}/spiders/{self.id}' links = { 'project': { 'related': '/api/projects/{self.project.id}', }, 'samples': { 'related': '/api/projects/{self.project.id}/spiders/{self.id}' '/samples', }, } default_kwargs = { 'exclude_map': { 'spiders': [ 'samples', ] } } def delete(self): project = self.instance.project project.schemas # preload schemas and fields super(SpiderSerializer, self).delete() class SampleSerializer(JsonApiSerializer): class Meta: model = Sample url = ('/api/projects/{self.spider.project.id}/spiders' '/{self.spider.id}/samples/{self.id}') links = { 'spider': { 'related': '/api/projects/{self.spider.project.id}/spiders' '/{self.spider.id}', }, 'items': { 'related': '/api/projects/{self.spider.project.id}/spiders' '/{self.spider.id}/samples/{self.id}/items' '?filter[parent]=null', }, } default_kwargs = { 'exclude_map': { 'samples': [ 'page-id', 'page-type', 'original-body', 'annotated-body', ] } } def create(self, validated_data): sample = super(SampleSerializer, self).create(validated_data) project = sample.spider.project schemas = project.schemas schema = next((s for s in schemas if s.default), None) if schema is None: schema_names = map(attrgetter('name'), schemas) schema_name = unique_name(sample.name, schema_names) schema = Schema(self.storage, id=AUTO_PK, name=schema_name, project=project, auto_created=True) schema.save() item = Item(self.storage, id=AUTO_PK, sample=sample, schema=schema) item.save() return sample def update(self, instance, validated_data): sample = super(SampleSerializer, self).update(instance, validated_data) for schema in sample.spider.project.schemas: schema.save() return sample class ItemSerializer(JsonApiSerializer): class Meta: model = Item url = ('/api/projects/{self.owner_sample.spider.project.id}/spiders' '/{self.owner_sample.spider.id}/samples/{self.owner_sample.id}' '/items/{self.id}') links = { 'sample': { 'related': '/api/projects/{self.sample.spider.project.id}' '/spiders/{self.sample.spider.id}/samples' '/{self.sample.id}', }, 'parent': { 'related': '/api/projects/{self.owner_sample.spider.project.id}' '/spiders/{self.owner_sample.spider.id}/samples' '/{self.owner_sample.id}/items/{self.parent.id}', }, 'schema': { 'related': '/api/projects/{self.owner_sample.spider.project.id}' '/schemas/{self.schema.id}', }, 'annotations': { 'related': '/api/projects/{self.owner_sample.spider.project.id}' '/spiders/{self.owner_sample.spider.id}/samples' '/{self.owner_sample.id}/annotations' '?filter[parent]={self.id}', }, } def create(self, validated_data): item = super(ItemSerializer, self).create(validated_data) if item.schema is None: sample = item.owner_sample project = sample.spider.project schema_names = map(attrgetter('name'), project.schemas) schema_name = unique_name(sample.name, schema_names, initial_suffix=1) schema = Schema(self.storage, id=AUTO_PK, name=schema_name, project=project, auto_created=True) schema.items.add(item) schema.save() if item.parent and item.name is None: sample = item.owner_sample item_names = map(attrgetter('name'), sample.ordered_items) item.name = unique_name('subitem', item_names, initial_suffix=1) item.save(only=('name',)) return item def update(self, instance, validated_data): current_schema = instance.schema instance = super(ItemSerializer, self).update(instance, validated_data) new_schema = instance.schema if new_schema != current_schema: field_map = {field.name: field for field in new_schema.fields} for annotation in instance.annotations: current_field = annotation.field if current_field.name in field_map: new_field = field_map[current_field.name] clear_auto_created(new_field) else: new_field = Field(self.storage, id=AUTO_PK, name=current_field.name, type=current_field.type, schema=new_schema, auto_created=True) field_map[new_field.name] = new_field new_field.save() annotation.field = new_field annotation.save(only=('field',)) if current_field.auto_created: self.deleted.extend(current_field.delete()) if current_schema.auto_created: self.deleted.extend(current_schema.delete()) clear_auto_created(new_schema) return instance def delete(self): instance = self.instance sample = instance.owner_sample items = sample.items if len(items) == 1 and items[0] == instance: raise ProtectedError( u"Cannot delete item {} because it is the only item in the " u"sample {}".format(instance, sample)) super(ItemSerializer, self).delete() class AnnotationSerializer(JsonApiSerializer): class Meta: model = Annotation url = ('/api/projects/{self.owner_sample.spider.project.id}/spiders' '/{self.owner_sample.spider.id}/samples/{self.owner_sample.id}' '/annotations/{self.id}') links = { 'parent': { 'related': '/api/projects' '/{self.owner_sample.spider.project.id}/spiders' '/{self.owner_sample.spider.id}/samples' '/{self.owner_sample.id}/items/{self.parent.id}', }, 'field': { 'related': '/api/projects' '/{self.owner_sample.spider.project.id}/schemas' '/{self.parent.schema.id}/fields/{self.field.id}', }, } def create(self, validated_data): annotation = super(AnnotationSerializer, self).create(validated_data) if annotation.field is None: project = annotation.owner_sample.spider.project project.schemas # preload schemas and fields item = annotation.parent schema = item.schema field_names = map(attrgetter('name'), schema.fields) field_name = unique_name('field', field_names, initial_suffix=1) field = Field(self.storage, id=AUTO_PK, name=field_name, type=choose_field_type(annotation), schema=schema, auto_created=True) field.annotations.add(annotation) field.save() return annotation def update(self, instance, validated_data): current_field = instance.field instance = super(AnnotationSerializer, self).update( instance, validated_data) new_field = instance.field if new_field != current_field: if current_field.auto_created: self.deleted.extend(current_field.delete()) clear_auto_created(new_field) return instance class RenderedBodySerializer(JsonApiSerializer): class Meta: model = RenderedBody url = ('/api/projects/{self.sample.spider.project.id}/' 'spiders/{self.sample.spider.id}/samples/' '{self.sample.id}/rendered_body') links = { 'sample': { 'related': ('/api/projects/{self.sample.spider.project.id}/' 'spiders/{self.sample.spider.id}/samples/' '{self.sample.id}'), }, } class OriginalBodySerializer(JsonApiSerializer): class Meta: model = OriginalBody url = ('/api/projects/{self.sample.spider.project.id}/' 'spiders/{self.sample.spider.id}/samples/' '{self.sample.id}/original_body') links = { 'sample': { 'related': ('/api/projects/{self.sample.spider.project.id}/' 'spiders/{self.sample.spider.id}/samples/' '{self.sample.id}'), }, } ================================================ FILE: portia_server/portia_api/resources/spiders.py ================================================ from django.http.response import Http404 from rest_framework.decorators import detail_route from rest_framework.response import Response from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST from django.conf import settings from scrapy.utils.misc import load_object from .projects import BaseProjectModelRoute, ProjectDownloadMixin from ..jsonapi.exceptions import JsonApiGeneralException from ..utils.extract import Pages, FetchError from ..utils.spiders import load_spider from portia_orm.models import Spider Deployer = load_object(settings.PROJECT_DEPLOYER) class SpiderRoute(ProjectDownloadMixin, BaseProjectModelRoute): lookup_url_kwarg = 'spider_id' lookup_value_regex = '[^/]+' default_model = Spider def get_instance(self): return self.get_collection()[self.kwargs.get('spider_id')] def get_collection(self): return self.project.spiders @detail_route(methods=['post']) def extract(self, *args, **kwargs): try: instance = self.get_instance() except KeyError: raise JsonApiGeneralException( 'No spider found with the name "%s"' % kwargs.get('spider_id'), 404) try: spider = load_spider(instance) except (ValueError, KeyError, IndexError): raise JsonApiGeneralException( 'Failed to load spider, "%s" correctly' % instance.id, 500) pages = self._build_pages(spider) try: data = pages.extract_items() except FetchError as e: raise JsonApiGeneralException(e.message, e.status) return Response(data, status=HTTP_200_OK) def _build_pages(self, spider): return Pages(self.data, spider) @detail_route(methods=['post']) def rename(self, *args, **kwargs): try: spider = self.get_instance() name = self.data['name'] self.project.spiders possible_spider = Spider(self.storage, id=name) if possible_spider in self.project.spiders and name != spider.id: raise JsonApiGeneralException( 'Spider already exists in this project with the name, ' '"%s"' % name, HTTP_400_BAD_REQUEST) path = 'spiders/{}/{}'.format for sample in spider.samples: # Load sample and move html pages sample.url self.storage.move(path(spider.id, sample.id), path(name, sample.id)) spider.id = name spider.save() self.storage.commit() except (TypeError, IndexError, KeyError): raise Http404 data = self.get_serializer(spider).data return Response(data, status=HTTP_200_OK) @detail_route(methods=['post']) def schedule(self, *args, **kwargs): spider_id = self.data['data']['id'] data = Deployer(self.project).schedule(spider_id) return Response(data, status=HTTP_200_OK) ================================================ FILE: portia_server/portia_api/routers.py ================================================ from rest_framework_nested.routers import SimpleRouter, NestedSimpleRouter __all__ = [ 'Router', 'NestedRouter', ] class Router(SimpleRouter): def __init__(self, trailing_slash=False): super(Router, self).__init__(trailing_slash) def get_lookup_regex(self, viewset, lookup_prefix=''): return super(Router, self).get_lookup_regex(viewset, '') class NestedRouter(NestedSimpleRouter, Router): def __init__(self, parent_router, parent_prefix, trailing_slash=False, *args, **kwargs): super(NestedRouter, self).__init__( parent_router, parent_prefix, trailing_slash, *args, **kwargs) ================================================ FILE: portia_server/portia_api/tests/__init__.py ================================================ ================================================ FILE: portia_server/portia_api/tests/test_routes.py ================================================ import unittest from rest_framework.test import APIRequestFactory from portia_api.resources.route import JsonApiRoute class TestRoute(unittest.TestCase): def test_route_representation(self): factory = APIRequestFactory() request = factory.get('/projects/') route = JsonApiRoute(request=request) self.assertEqual(str(route), 'GET /projects/') self.assertEqual(repr(route), 'Route(GET /projects/)') ================================================ FILE: portia_server/portia_api/urls.py ================================================ from django.conf.urls import url, include from .routers import Router, NestedRouter from .resources.annotations import AnnotationRoute from .resources.extractors import ExtractorRoute from .resources.fields import FieldRoute from .resources.items import ItemRoute from .resources.projects import ProjectRoute from .resources.samples import SampleRoute from .resources.schemas import SchemaRoute from .resources.spiders import SpiderRoute router = Router() router.register(r'projects', ProjectRoute, base_name='projects') project_router = NestedRouter(router, r'projects') project_router.register(r'schemas', SchemaRoute, base_name='schemas') project_router.register(r'spiders', SpiderRoute, base_name='spiders') project_router.register(r'extractors', ExtractorRoute, base_name='extractors') schema_router = NestedRouter(project_router, r'schemas') schema_router.register(r'fields', FieldRoute, base_name='fields') spider_router = NestedRouter(project_router, r'spiders') spider_router.register(r'samples', SampleRoute, base_name='samples') sample_router = NestedRouter(spider_router, r'samples') sample_router.register(r'items', ItemRoute, base_name='items') sample_router.register(r'annotations', AnnotationRoute, base_name='annotations') urlpatterns = [ url(r'^', include(router.urls)), url(r'^', include(project_router.urls)), url(r'^', include(schema_router.urls)), url(r'^', include(spider_router.urls)), url(r'^', include(sample_router.urls)), ] ================================================ FILE: portia_server/portia_api/utils/__init__.py ================================================ ================================================ FILE: portia_server/portia_api/utils/annotations.py ================================================ DEFAULTS = { 'accept': 'url', 'align': 'number', 'code': 'url', 'codebase': 'url', 'coords': 'geopoint', 'data': 'url', 'datetime': 'date', 'download': 'url', 'high': 'number', 'href': 'url', 'icon': 'image', 'low': 'number', 'max': 'number', 'media': 'href', 'min': 'number', 'optimum': 'number', 'rel': 'href', 'rows': 'number', 'src': 'image', 'target': 'url', } def choose_field_type(annotation): attribute = annotation.attribute if attribute == 'content': return 'text' return DEFAULTS.get(attribute, 'text') ================================================ FILE: portia_server/portia_api/utils/copy.py ================================================ import re from collections import defaultdict from portia_orm.models import Project from portia_orm.utils import short_guid class MissingModelException(Exception): """Error thrown when model for id is not present in project.""" class ModelCopier(object): SPIDER_NAME = r'(.*_)([0-9]+)$' def __init__(self, project, storage, from_project_id): self.project, self.storage = project, storage self.from_storage = storage.__class__(from_project_id, author=storage.author) self.from_project = Project(self.from_storage, id=from_project_id, name=from_project_id) # Populating projects to avoid overwrites self.project.schemas self.project.extractors self.from_project.schemas self.from_project.extractors self.spider_ids = set(spider.id for spider in self.project.spiders) self.copied_fields = {} self.copied_schemas = {} self.copied_extractors = {} def copy(self, models): grouped = self.group(models) for spider in grouped.get('spiders', []): copied_spider = self.copy_spider(spider) for sample in spider.samples: copied_sample = self.copy_sample(sample, copied_spider) for item in sample.items: copied_item = self.copy_item( item, self.copy_schema(item.schema), copied_sample) for annotation in item.annotations: copied_ann = self.copy_annotation( annotation, copied_item, annotation.field) copied_ann.extractors = self.copy_extractors( annotation.extractors) copied_ann.save() for schema in grouped.get('schemas', []): self.copy_schema(schema) self.storage.commit() def copy_spider(self, spider): copied_spider = spider.copy(self._unique_id(spider.id), storage=self.storage) copied_spider.project = self.project copied_spider.save() return copied_spider def copy_sample(self, sample, spider): copied_sample = sample.copy(short_guid(), storage=self.storage) copied_sample.spider = spider copied_sample.original_body = self._copy_body( sample.original_body, sample) try: copied_sample.rendered_body = self._copy_body( sample.rendered_body, sample) except AttributeError: # Ignore missing rendered body. # It will be added when the sample is modified pass copied_sample.save() return copied_sample def copy_item(self, item, schema, sample): copied_item = item.copy(storage=self.storage) copied_item.schema = schema copied_item.sample = sample copied_item.save() return copied_item def copy_schema(self, schema): schema_id = schema.id if schema_id in self.copied_schemas: return self.copied_schemas[schema_id] copied_schema = schema.copy(storage=self.storage) copied_schema.project = self.project copied_schema.save() for field in schema.fields: self._copy_field(field, copied_schema) self.copied_schemas[schema_id] = copied_schema return copied_schema def copy_annotation(self, annotation, item, field): copied_ann = annotation.copy( '{}|{}'.format(short_guid(), short_guid()), storage=self.storage) copied_ann.field = self.copied_fields[field.id] item.annotations.add(copied_ann) copied_ann.save() return copied_ann def copy_extractors(self, extractors): copied = [] for extractor in extractors: # TODO: Skip missing extractors in ORM try: self.from_project.extractors[extractor] except KeyError: continue copied_extractor = self._copy_extractor(extractor) copied.append(copied_extractor) return copied def group(self, models): instances = defaultdict(list) errors = [] for model_meta in models: _id, model_type = model_meta['id'], model_meta['type'] collection = getattr(self.from_project, model_type, {}) try: instance = collection[_id] instances[model_type].append(instance) except (KeyError, TypeError): errors.append(_id) if errors: raise MissingModelException(errors) return instances def _copy_field(self, field, schema): copied_field = field.copy(storage=self.storage) copied_field.schema = schema copied_field.save() self.copied_fields[field.id] = copied_field def _copy_extractor(self, extractor): extractor_id = extractor.id if extractor_id in self.copied_extractors: return self.copied_extractors[extractor_id] copied_extractor = extractor.copy(short_guid(), storage=self.storage) copied_extractor.project = self.project copied_extractor.save() self.copied_extractors[extractor_id] = copied_extractor return copied_extractor def _copy_body(self, body, sample): body_id = '{}_{}'.format(sample.id, body.Meta.name) copied_body = body.copy(body_id, storage=self.storage) copied_body.sample = sample copied_body.save() return copied_body def _unique_id(self, spider_id): unique_id = spider_id while unique_id in self.spider_ids: match = re.match(self.SPIDER_NAME, unique_id) if match: unique_id = match.group(1) + str(int(match.group(2)) + 1) else: unique_id += '_1' return unique_id ================================================ FILE: portia_server/portia_api/utils/deploy/base.py ================================================ from portia_api.utils.download import ProjectArchiver class BaseDeploy(object): def __init__(self, project): self.project = project self.storage = project.storage self.config = self._get_config() self.config.version = self.project.version def build_archive(self): return ProjectArchiver(self.storage, project=self.project).archive( egg_info=True) def _get_config(self): raise NotImplementedError def deploy(self, target=None): raise NotImplementedError def schedule(self, spider, args=None, settings=None, target=None): raise NotImplementedError ================================================ FILE: portia_server/portia_api/utils/deploy/package.py ================================================ import os import textwrap import zipfile from datetime import datetime from distutils.dist import DistributionMetadata from io import StringIO class EggInfo(object): def __init__(self, project, archive): self.project = project self.archive = archive self.tstamp = datetime.now().timetuple()[:6] def write(self): self._write_file('PKG-INFO', self.build_pkg_info()) self._write_file('SOURCES.txt', self.build_sources()) self._write_file('dependency_links.txt', self.build_dependency()) self._write_file('entry_points.txt', self.build_entry_points()) self._write_file('top_level.txt', self.build_top_level()) self._write_file('zip-safe', self.build_zip_safe()) def _write_file(self, filename, contents): filepath = os.path.join('EGG-INFO', filename) fileinfo = zipfile.ZipInfo(filepath, self.tstamp) fileinfo.external_attr = 0o666 << 16 self.archive.writestr(fileinfo, contents, zipfile.ZIP_DEFLATED) def build_pkg_info(self): meta = DistributionMetadata() meta.name = self.project.name meta.version = self.project.version file = StringIO() meta.write_pkg_file(file) file.seek(0) return file.read() def build_sources(self): return '\n'.join(sorted(f.filename for f in self.archive.filelist)) def build_top_level(self): return '\n'.join(sorted({ fn.split('/', 1)[0] for fn in ( fn for fn in ( f.filename for f in self.archive.filelist)) if fn.endswith('.py') })) def build_dependency(self): return '\n' def build_entry_points(self): return textwrap.dedent("""\ [scrapy] settings = spiders.settings """) def build_zip_safe(self): return '' ================================================ FILE: portia_server/portia_api/utils/deploy/scrapinghub.py ================================================ import json import os from six import StringIO from urllib.parse import urljoin from django.conf import settings as app_settings from rest_framework import status from shub import exceptions from shub.config import ShubConfig from shub.schedule import schedule_spider from shub.utils import make_deploy_request from portia_api.jsonapi.exceptions import JsonApiGeneralException from storage.projecttemplates import templates from .base import BaseDeploy class ScrapinghubDeploy(BaseDeploy): SHUB_DOCS_URL = 'https://shub.readthedocs.io/en/stable/configuration.html' EXCEPTIONS = ( exceptions.InvalidAuthException, # EX_NOPERM exceptions.RemoteErrorException, # EX_PROTOCOL ) STATUS_CODES = { os.EX_UNAVAILABLE: status.HTTP_404_NOT_FOUND, os.EX_PROTOCOL: status.HTTP_503_SERVICE_UNAVAILABLE, } def _get_config(self): conf = ShubConfig() conf.load(StringIO(json.dumps(self._default_config()))) if 'SHUB_APIKEY' in os.environ: conf.apikeys['default'] = os.environ['SHUB_APIKEY'] try: conf.load(self.storage.open('scrapinghub.yml')) except OSError: raise ('Need a `scrapinghub.yml` file to identify which project ' 'to deploy to. Find more information at: {}'.format( self.SHUB_DOCS_URL )) return conf def _default_config(self): config = { 'stack': 'scrapy:1.5-py-latest', } if getattr(app_settings, 'SCRAPINGHUB_APIKEY', None): config['apikeys'] = { 'default': app_settings.SCRAPINGHUB_APIKEY, } return config def deploy(self, target='default'): try: conf = self.config.get_target_conf(target) archive = self.build_archive() data = { 'project': conf.project_id, 'version': self.project.version, 'stack': conf.stack } files = [('egg', archive)] if conf.requirements_file: try: file = self.storage.open(conf.requirements_file) except OSError: file = StringIO(templates['REQUIREMENTS']) files.append(('requirements', file)) make_deploy_request( urljoin(conf.endpoint, 'scrapyd/addversion.json'), data, files, (conf.apikey, ''), False, False) except self.EXCEPTIONS as e: raise JsonApiGeneralException( e.format_message(), self.STATUS_CODES.get(getattr(e, 'exit_code', None), 500), ) return { 'message': 'Your deploy completed successfully', } def schedule(self, spider, args=None, settings=None, target='default'): try: conf = self.config.get_target_conf(target) schedule_spider( conf.project_id, conf.endpoint, conf.apikey, spider, arguments=args or (), settings=settings or ()) except self.EXCEPTIONS as e: raise JsonApiGeneralException( e.format_message(), self.STATUS_CODES.get(getattr(e, 'exit_code', None), 500), ) ================================================ FILE: portia_server/portia_api/utils/deploy/scrapyd.py ================================================ import requests from configparser import ConfigParser from urllib.parse import urljoin from django.conf import settings as app_settings from portia_api.jsonapi.exceptions import JsonApiGeneralException from .base import BaseDeploy class ScrapydDeploy(BaseDeploy): def _get_config(self): conf = ConfigParser() conf.read_dict(self._get_config_defaults()) if getattr(app_settings, 'SCRAPYD_CFG_DEFAULT', None): conf.read(app_settings.SCRAPYD_CFG_DEFAULT) try: scrapy_cfg = self.storage.open('scrapy.cfg').read().decode('utf-8') conf.read_string(scrapy_cfg) except OSError: pass return conf def _get_config_defaults(self): deploy_settings = [ ('username', 'SCRAPYD_USERNAME'), ('password', 'SCRAPYD_PASSWORD'), ('url', 'SCRAPYD_URL'), ] deploy_defaults = {} for default, setting in deploy_settings: setting = getattr(app_settings, setting, None) if setting is not None: deploy_defaults[default] = setting defaults = { 'deploy': deploy_defaults, 'deploy:default': { 'project': self.project.name, 'version': self.project.version, }, } return defaults def deploy(self, target='default'): cfg = dict(self.config.items('deploy')) cfg.update(self.config.items('deploy:default')) if target and self.config.has_section('deploy:{}'.format(target)): cfg.update(self.config.items('deploy:{}'.format(target))) data = { 'project': cfg['project'], 'version': cfg['version'], } files = { 'egg': ('project.egg', self.build_archive()) } url = urljoin(cfg['url'], '/addversion.json') user = cfg.get('username') if user: auth = (user, cfg.get('password', '')) else: auth = None requests.post(url, data=data, files=files, auth=auth) return { 'message': 'Your deploy completed successfully', } def schedule(self, spider, args=None, settings=None, target=None): schedule_data = self._schedule_data( spider, self._schedule_data(spider, args)) request = requests.post( urljoin(app_settings.SCRAPYD_URL, 'schedule.json'), data=schedule_data) if request.status_code != 200: raise JsonApiGeneralException( request.status_code, request.content) data = {} data.setdefault('meta', {})['scheduled'] = True return data def _schedule_data(self, spider_id, args): data = { 'project': self.project.id, 'spider': spider_id } if self.storage.version_control: branch = self.query.get('branch', None) commit = self.query.get('commit_id', None) if not branch and self.storage.repo.has_branch(self.user.username): branch = self.user.username self.storage.checkout(commit, branch) commit_id = self.storage._commit.id data['version'] = commit_id return data ================================================ FILE: portia_server/portia_api/utils/download.py ================================================ from __future__ import absolute_import import itertools import json import os import six import zipfile from collections import defaultdict from os.path import join from six import BytesIO from datetime import datetime from slybot.utils import decode from portia2code.porter import load_project_data, port_project from storage.projecttemplates import templates from portia_api.utils.deploy.package import EggInfo REQUIRED_FILES = {'setup.py', 'scrapy.cfg', 'extractors.json', 'items.json', 'project.json', 'spiders/__init__.py', 'spiders/settings.py', 'requirements.txt', 'MANIFEST.in'} FILE_TEMPLATES = { 'extractors.json': '{}', 'items.json': '{}', 'project.json': templates['PROJECT'], 'scrapy.cfg': templates['SCRAPY'], 'setup.py': templates['SETUP'], 'MANIFEST.in': templates['MANIFEST'], 'requirements.txt': templates['REQUIREMENTS'], 'spiders/__init__.py': '', 'spiders/settings.py': templates['SETTINGS'] } def walk(storage, dirname=''): dirs, files = storage.listdir(dirname) for dname in dirs: files.extend([join(dname, fname) for fname in walk(storage, join(dirname, dname))]) return set(files) class ProjectArchiver(object): required_files = frozenset(REQUIRED_FILES) file_templates = FILE_TEMPLATES def __init__(self, storage, required_files=None, *, project=None): self.separator = os.path.sep self.storage = storage self.name = storage.name self.project = project if required_files is not None: self.required_files = required_files def archive(self, spiders=None, **kwargs): """ Zip the contents or a subset of the contents in this project together """ zbuff = BytesIO() self._archive = zipfile.ZipFile(zbuff, "w", zipfile.ZIP_DEFLATED) self._add_files(spiders) if kwargs.get('egg_info'): self.add_egg_info() self._archive.close() zbuff.seek(0) return zbuff def _add_files(self, spiders): """ Add all selected spiders and other files to the project """ now = datetime.now().timetuple()[:6] extractors = self.read_file('extractors.json', deserialize=True) or {} files, all_files, spider_templates = self._paths(spiders) seen_files = set() for file_path in files: if file_path in seen_files: continue if (file_path.startswith('spiders/') and file_path.endswith('.json')): path, contents, added = self._add_spider(file_path, spider_templates, extractors) if contents is not None: self._add_file(file_path, contents, now) else: self._add_file(file_path, self.read_file(file_path), now) file_list = set(f.filename for f in self._archive.filelist) for file_path in self.required_files: if file_path in file_list: continue self._add_file(file_path, self.file_templates[file_path], now) def _add_file(self, filename, contents, tstamp): """ Add a file to the zip archive. """ if filename is None or contents in (None, 'null'): return fileinfo = zipfile.ZipInfo(filename, tstamp) fileinfo.external_attr = 0o666 << 16 self._archive.writestr(fileinfo, contents, zipfile.ZIP_DEFLATED) def _add_spider(self, file_path, templates, extractors): """ Add a spider or template to the archive. """ data = self.read_file(file_path, deserialize=True) added = {file_path} if data is not None and data.get('deleted'): return self._deleted_spider(file_path, data, templates) spider_content = json.dumps(data, sort_keys=True, indent=4) return file_path, spider_content.encode('utf-8'), added def _deleted_spider(self, file_path, spider_data, templates): """ Add information about a deleted spider. """ spider = self._spider_name(file_path) file_path = self._spider_path(file_path) added = {file_path} added.update(set(templates.get(spider, []))) if self.ignore_deleted: return None, None, added spider_content = json.dumps(spider_data, sort_keys=True, indent=4) return file_path, spider_content.encode('utf-8'), added def _spider_templates(self, spider_templates, extractors): """ Find all templates for a legacy spider and combine them into a single list. """ templates, added = [], set() for template_path in spider_templates: added.add(template_path) existing = {} template = self.read_file(template_path, deserialize=True) if template is None: continue template_extractors = template.get('extractors', {}) if not isinstance(template_extractors, dict): template_extractors = {e.get('field'): e.get('id') for e in template_extractors if 'field' in e and e['field']} for field, eids in template_extractors.items(): existing[field] = [eid for eid in eids if eid in extractors] template['extractors'] = existing templates.append(template) return templates, added def add_egg_info(self): EggInfo(self.project, self._archive).write() def _spider_name(self, file_path): """ Get the name of a spider for a template or spider path. """ split = file_path.split(self.separator) if len(split) > 2: return split[1] return split[1][:-5] def _name(self, file_path): """ Get the name for the current json path """ split = file_path.split(self.separator) if split[-1].endswith('.json'): return split[-1][:-5] return '' def _spider_path(self, file_path): if len(file_path.split(self.separator)) > 2: return 'spiders/{}.json'.format(self._spider_name(file_path)) return file_path def _paths(self, spiders): """ Build a collection of paths needed to build the archive. """ if spiders is None: all_files = self.list_files() return all_files, all_files, self._template_paths(None, all_files) if isinstance(spiders, six.string_types): spiders = [spiders] spider_paths = set('spiders/{}.json'.format(spider) for spider in spiders) all_files = self.list_files() template_paths = self._template_paths(spiders, all_files) templates = set(itertools.chain(*template_paths.values())) spider_paths = spider_paths | templates files = list(set(spider_paths) | self.required_files) return files, all_files, template_paths def _template_paths(self, spiders, files): """ Map all template paths to the corresponding spider. """ spider_templates = defaultdict(list) for file_path in files: split_file_path = file_path.split('/') if len(split_file_path) > 2 and (spiders is None or split_file_path[1] in spiders): spider_templates[split_file_path[1]].append(file_path) return spider_templates def list_files(self): return walk(self.storage) def read_file(self, filename, deserialize=False): try: contents = self.storage.open(filename, 'rb').read() except IOError as e: if filename in ('items.json', 'extractors.json'): return {} if deserialize else b'{}' elif filename in FILE_TEMPLATES: return FILE_TEMPLATES[filename].encode('utf-8') raise e if deserialize and contents is not None: return json.loads(contents.decode('utf-8')) return contents class CodeProjectArchiver(ProjectArchiver): def archive(self, spiders=None, **kwargs): class ArchivingStorage(object): def __init__(self, storage): self.storage = storage def isdir(self, *args, **kwargs): return self.storage.isdir(self.rel_path(*args)) def listdir(self, *args, **kwargs): if spiders and args == ['spiders']: return ['{}.json'.format(s) for s in spiders] path = self.rel_path(*args) return itertools.chain(*self.storage.listdir(path)) def rel_path(self, *args): return '/'.join(args) def open(self, *args, **kwargs): raw = kwargs.get('raw') path = self.rel_path(*args) if raw: fp = self.storage.open(path) else: fp = self.storage.open_with_default(path, {}) return decode(fp.read()) if raw else json.loads(fp.read()) storage = ArchivingStorage(self.storage) schemas, extractors, spiders = load_project_data(storage) name = self._process_name() selector = kwargs.get('selector') or 'css' return port_project(name, schemas, spiders, extractors, selector=selector) def _process_name(self): try: int(self.name) except ValueError: return self.name # Scrapy will not allow the use of a number as a project name return 'A{}'.format(self.name) ================================================ FILE: portia_server/portia_api/utils/extract.py ================================================ import logging from twisted.internet import defer from twisted.web.client import getPage from scrapy import Request from scrapy.http import HtmlResponse from scrapy.utils.misc import arg_to_iter from crochet import setup, wait_for, TimeoutError setup() class FetchError(Exception): status = 400 def __init__(self, errors): for error in errors: print(vars(error)) self.errors = errors self.message = str(self) def __str__(self): return '\n'.join(e.getErrorMessage() for e in self.errors) def get_page(times, url): errors = [] deferred = defer.Deferred() def run(): d = getPage(url) d.addCallbacks(lambda html: deferred.callback((url, html)), error) def error(error): errors.append(error) retry = True if len(errors) < times else False logging.warn('Failed to get %s %d times, %s', url, len(errors), 'retrying' if retry else 'stop') run() if retry else deferred.errback((url, errors)) run() return deferred def _load_urls(urls): deferreds = [] for url in urls: deferreds.append(get_page(3, url.encode('utf-8'))) return defer.DeferredList(deferreds) @wait_for(timeout=50) def load_urls(urls): return _load_urls(urls) class Pages(object): def __init__(self, urls, spider): if hasattr(urls, 'get'): urls = urls.get('urls', []) if isinstance(urls, dict): self.urls = urls.items() else: self.urls = urls self.spider = spider def fetch(self): try: responses = load_urls(self.urls) except TimeoutError: raise FetchError(['Requests timed out, try loading fewer urls']) results, errors = [], [] for success, result in responses: if not success: errors.append(result.value[1][-1]) else: results.extend(arg_to_iter(self.process(*result))) if errors and not results: raise FetchError(errors) return results def process(self, url, page): return HtmlResponse(url, body=page, request=Request(url)) def extract_items(self): responses = self.fetch() items = [] for response in responses: page_key = response.meta.get('page_key') or response.url item = {'key': page_key, 'items': None, 'templates': None} extracted_items = [dict(i) for i in self.spider.parse(response) if not isinstance(i, Request)] if extracted_items: item['items'] = extracted_items item['templates'] = [i['_template'] for i in extracted_items if i.get('_template')] items.append(item) return items ================================================ FILE: portia_server/portia_api/utils/projects.py ================================================ def unique_name(base_name, disallow=(), initial_suffix=''): disallow = set(disallow) suffix = initial_suffix while True: name = u'{}{}'.format(base_name, suffix) if name not in disallow: break try: suffix += 1 except TypeError: suffix = 1 return name ================================================ FILE: portia_server/portia_api/utils/spiders.py ================================================ import json from scrapy.settings import Settings from slybot.spider import IblSpider def load_spider_data(model): storage = model.storage items = json.load(storage.open_with_default('items.json', {})) extractors = json.load(storage.open_with_default('extractors.json', {})) spider = json.loads(model.dumps()) spider['templates'] = [] samples = [] for sample in model.samples: json_sample = json.loads(sample.dumps()) default = u'' for key in ('original_body', 'rendered_body'): try: html = getattr(sample, key).html assert html json_sample[key] = html except (IOError, AttributeError, AssertionError): json_sample[key] = default else: default = json_sample[key] samples.append(json_sample) spider['templates'] = samples return model.id, spider, items, extractors def load_spider(model): name, spider, items, extractors = load_spider_data(model) return IblSpider(name, spider, items, extractors, Settings()) ================================================ FILE: portia_server/portia_orm/__init__.py ================================================ ================================================ FILE: portia_server/portia_orm/apps.py ================================================ from __future__ import unicode_literals from django.apps import AppConfig class PortiaOrmConfig(AppConfig): name = 'portia_orm' ================================================ FILE: portia_server/portia_orm/base.py ================================================ from collections import OrderedDict from itertools import chain import errno import json import re from toposort import toposort_flatten from storage.backends import ContentFile from .collection import ModelCollection from .datastore import shared_data from .deletion import Collector from .exceptions import (ImproperlyConfigured, PathResolutionError, ValidationError) from .fields import Field from .registry import models, get_polymorphic_model from .relationships import BaseRelationship from .serializers import FileSerializer from .snapshots import ModelSnapshots from .utils import (cached_property, class_property, short_guid, unspecified, AttributeDict) __all__ = [ 'Model', ] AUTO_PK = object() class ModelOpts(object): """Meta options for Models.""" def __init__(self, meta, model): self.path = getattr(meta, 'path', None) if self.path is not None and not isinstance(self.path, str): raise ValueError("'path' option must be a string or None.") self.owner = getattr(meta, 'owner', False) if self.owner is not False and not isinstance(self.owner, str): raise ValueError("'owner' option must be a string or False.") if self.owner and not isinstance(model._fields.get(self.owner), BaseRelationship): raise ValueError("'owner' option must be a relationship name.") self.polymorphic = getattr(meta, 'polymorphic', False) if not isinstance(self.polymorphic, (bool, str)): raise ValueError( "'polymorphic' option must be a string or boolean.") self.initialize_boolean('raw', meta) self.initialize_boolean('single', meta) self.initialize_boolean('ignore_if_missing', meta) def initialize_boolean(self, key, meta): value = getattr(meta, key, False) if not isinstance(value, bool): raise ValueError("'{}' option must be a boolean".format(key)) setattr(self, key, value) class ModelMeta(type): """Meta class for models""" def __new__(mcs, name, bases, attrs): parents = [b for b in bases if isinstance(b, ModelMeta)] if not parents: return super(ModelMeta, mcs).__new__(mcs, name, bases, attrs) # check if a model with the same name exists in the registry if name in models: raise ImproperlyConfigured( u"A Model named '{}' already exists".format(name)) meta = attrs.pop('Meta', None) meta_bases = tuple(parent.Meta for parent in parents) + (object,) if meta: meta_bases = (meta,) + meta_bases meta = type('Meta', meta_bases, {}) primary_key = None fields = {} basic_attrs = { 'Meta': meta, } file_schema_attrs = {} for attrs in chain([attrs], (getattr(parent, '_class_attrs', {}) for parent in parents)): for attrname, value in attrs.items(): if isinstance(value, BaseRelationship): fields[attrname] = value elif isinstance(value, Field): if value.primary_key: if primary_key: raise ImproperlyConfigured( u"Model '{}' declared with more than one primary " u"key".format(name)) primary_key = attrname fields[attrname] = value # move decorated marshmallow methods to the file schema elif hasattr(value, '__marshmallow_tags__'): file_schema_attrs[attrname] = value else: basic_attrs[attrname] = value if fields and not primary_key: raise ImproperlyConfigured( u"Model '{}' declared with no primary key".format(name)) class_attrs = {} class_attrs.update(fields) class_attrs.update(file_schema_attrs) class_attrs.update(basic_attrs) cls = super(ModelMeta, mcs).__new__(mcs, name, bases, basic_attrs) cls._class_attrs = class_attrs cls._pk_field = primary_key cls._fields = fields cls._file_fields = file_fields = {k for k, f in fields.items() if not f.ignore_in_file} cls._field_names = sorted(k for k, f in fields.items() if isinstance(f, Field)) cls._relationship_names = sorted(k for k, f in fields.items() if isinstance(f, BaseRelationship)) cls.opts = ModelOpts(meta, cls) cls.collection = type(name + 'Collection', (ModelCollection,), { 'model': cls }) for attrname, field in fields.items(): if attrname in file_fields: file_schema_attrs[attrname] = field field.contribute_to_class(cls, attrname) # compute an safe order for setting fields during construction try: cls._ordered_fields = toposort_flatten({ attrname: field.get_dependencies(cls) for attrname, field in fields.items() }) except ValueError as e: raise ImproperlyConfigured(e.message) # build a marshmallow schema for the filesystem format file_schema_attrs['Meta'] = type('Meta', (meta,), { 'model': cls }) cls.file_schema = type(cls.__name__ + 'FileSerializer', (FileSerializer,), file_schema_attrs) # add new model to registry by name models[name] = cls return cls class Model(object, metaclass=ModelMeta): _own_attributes = {'data_key', 'storage', 'snapshots', '_initializing'} # set by metaclass _fields = None _field_names = None _relationship_names = None _ordered_fields = None _file_fields = None _pk_field = None collection = None file_schema = None opts = None snapshot_class = ModelSnapshots class Meta: pass def __init__(self, storage=None, snapshots=None, _data_key=unspecified, **kwargs): if _data_key is unspecified: if (self._pk_field not in kwargs or (kwargs[self._pk_field] is AUTO_PK and storage is None)): raise TypeError( u"Model '{}' must be initialized with a value for the '{}' " u"field".format(self.__class__.__name__, self._pk_field)) pk = kwargs[self._pk_field] if pk is AUTO_PK: pk = kwargs[self._pk_field] = self.generate_pk(storage) _data_key = self.__class__, pk self.data_key = _data_key self.storage = storage self.snapshots = snapshots or ModelSnapshots.default_snapshots for attrname in kwargs.keys(): if attrname not in self._fields: raise TypeError( u"'{}' is not a field of model '{}'".format( attrname, self.__class__.__name__)) errors = {} self._initializing = set(kwargs.keys()) for attrname in self._ordered_fields: if attrname in kwargs: try: setattr(self, attrname, kwargs[attrname]) except ValidationError as err: errors[attrname] = err.messages self._initializing.clear() if errors: raise ValidationError(errors) def __eq__(self, other): if isinstance(other, Model): return other.data_key == self.data_key if isinstance(other, tuple): self_class, self_pk = self.data_key other_class, other_pk = other return self_pk == other_pk and ( issubclass(self_class, other_class) or issubclass(other_class, self_class)) return False def __hash__(self): return hash(self.data_key) def __ne__(self, other): return not self.__eq__(other) def __repr__(self, *field_names): if field_names: if self._pk_field not in field_names: field_names = (self._pk_field,) + field_names else: field_names = [k for k, v in self._fields.items() if k != self._pk_field and isinstance(v, Field)] field_names.sort() field_names.insert(0, self._pk_field) data_store = self.data_store fields = OrderedDict() for field_name in field_names: try: fields[field_name] = data_store.get(field_name) except KeyError: pass return u'{}<{}>({})'.format( self.__class__.__name__, self.snapshots[0], u', '.join(u'{}={!r}'.format(k, v) for k, v in fields.items())) def __setattr__(self, key, value): if key not in self._own_attributes and key not in self._fields: raise TypeError( u"'{}' is not a field of model '{}'".format( key, self.__class__.__name__)) super(Model, self).__setattr__(key, value) def with_snapshots(self, snapshots=None): if self.snapshots == (snapshots or ModelSnapshots.default_snapshots): return self copy = self.__class__(self.storage, snapshots, _data_key=self.data_key) if copy.data_store is not self.data_store: copy.data_store.copy_from(self.data_store) return copy # share data between instances of the same model, to simplify relationships @class_property def shared_data_store(cls): return shared_data.data_store # keeps track of files that are loading @class_property def loaded(cls): return shared_data.loaded @class_property def _file_model(cls): """Find the top-level model stored in this model's path.""" model = getattr(cls, '_cached_file_model', unspecified) if model is not unspecified: return model path = cls.opts.path model = cls while True: if model.opts.owner: try: owner = model._fields[model.opts.owner].model path = re.sub(r'{{self.{}(\.|}})'.format(model.opts.owner), '{self\\1', path) if owner is not model and owner.opts.path == path: model = owner continue except KeyError: pass cls._cached_file_model = model return model @classmethod def generate_pk(cls, storage): data_stores = cls.shared_data_store.get(storage, {}) pk = short_guid() while (cls, pk) in data_stores: pk = short_guid() return pk @property def pk(self): return getattr(self, self._pk_field) @cached_property def data_store(self): if self.storage: return self.shared_data_store.setdefault( self.storage, {}).setdefault( self.data_key, self.snapshot_class()) return self.shared_data_store.setdefault(self, self.snapshot_class()) def has_data(self, key): try: self.get_data(key) except AttributeError: return False return True def get_data(self, key, default=unspecified): self.resolve_attributes(key) try: return self.data_store.get(key, snapshots=self.snapshots) except KeyError: pass if default is not unspecified: return default raise AttributeError( u"'{}' object has no attribute '{}'".format( self.__class__.__name__, key)) def set_data(self, key, value): self.data_store.set(key, value, snapshot=self.snapshots[0]) def dump(self, state='working'): try: index = ModelSnapshots.default_snapshots.index(state) except ValueError: raise ValueError(u"'{}' is not a valid state".format(state)) context = { 'snapshots': ModelSnapshots.default_snapshots[index:] } return self.file_schema(context=context).dump(self).data def dumps(self, state='working'): return json.dumps(self.dump(state=state), sort_keys=False, indent=4, separators=(', ', ': ')) def rollback(self): self.data_store.clear_snapshot('working') def save(self, only=None): if self.storage is None: return # make sure all attributes have been loaded before saving, we need them # to correctly detect path changes and to prevent data loss self.resolve_attributes(snapshots=('committed',)) # stage changes to the selected fields in the model and across # relationships self._stage_changes(only) # now that all changes are staged we can save from the staged and # committed snapshots to get a consistent save of the selected fields self._commit_changes() def _stage_changes(self, only=None): store = self.data_store dirty = store.dirty_fields('working', ('committed',)) if only is not None: dirty = dirty.intersection(only) if dirty: store.update_snapshot('staged', ('working',), fields=dirty) for model, field in self._staged_model_references(): related_store = model.data_store related_field = model._fields[field] if related_field.only is None: related_dirty = dirty elif isinstance(related_field.only, str): related_dirty = dirty.intersection((related_field.only,)) else: related_dirty = dirty.intersection(related_field.only) if related_dirty or field in related_store.dirty_fields( 'working', ('committed',)): related_store.update_snapshot( 'staged', ('working', 'committed'), fields=[field]) def _commit_changes(self, saved_paths=None, deleted_paths=None): if saved_paths is None: saved_paths = set() if deleted_paths is None: deleted_paths = set() for model in chain([self], (model for model, _ in self._staged_model_references())): store = model.data_store dirty = ( model._file_fields.intersection(store['staged'].keys()) or 'project' in store.dirty_fields('working', ('committed',)) ) path = model.storage_path(model, snapshots=('staged', 'committed')) old_path = model.storage_path(model, snapshots=('committed', 'staged')) if dirty or old_path != path: if path not in saved_paths and path not in deleted_paths: to_save = self._get_object_to_dump( model, parent_snapshots=('staged', 'committed')) model.storage.save(path, ContentFile( to_save.dumps(state='staged'), path)) saved_paths.add(path) if old_path != path and old_path not in deleted_paths: try: model.storage.delete(old_path) except IOError as ex: # Assume missing files are already deleted if ex.errno != errno.ENOENT: raise deleted_paths.add(old_path) for model in chain([self], (model for model, _ in self._staged_model_references())): store = model.data_store dirty = set(store['staged'].keys()) if dirty: store.update_snapshot('committed', ('staged',), fields=dirty) store.clear_snapshot('staged') store.clear_snapshot('working', fields=dirty.intersection( store['working'].keys())) def _get_object_to_dump(self, model, parent_snapshots): child = model while child.opts.owner: parent = child._get_parent_object(parent_snapshots) if isinstance(parent, ModelCollection): parent = next(iter(parent)) if parent is None: return to_save = getattr( parent.with_snapshots(('staged', 'committed')), child._fields[child.opts.owner].related_name) child = parent if child.__class__ is model._file_model: to_save = child return to_save def _get_parent_object(self, parent_snapshots): parent_field = self.opts.owner return getattr(self.with_snapshots(parent_snapshots), parent_field) def _staged_model_references(self, load_relationships=False): for name, field in self._fields.items(): if isinstance(field, BaseRelationship): try: if load_relationships: value = getattr(self, name) else: value = self.data_store.get( name, ('staged', 'committed')) except (AttributeError, KeyError, PathResolutionError): continue if value is None: continue if not isinstance(value, ModelCollection): value = [value] for related in value: related_name = field.related_name yield related, related_name def delete(self): if self.storage is None: return self.resolve_attributes(snapshots=('committed',)) collector = Collector() self._stage_delete(collector=collector) self._commit_delete(collector=collector) return collector.delete def _stage_delete(self, collector): if self in collector: return collector.add(self) collector.delete_instance(self) for model, field in self._staged_model_references( load_relationships=True): if model is None: continue related_field = model._fields[field] related_field.on_delete( collector, model.with_snapshots(('staged', 'committed')), field, self) def _commit_delete(self, collector, saved_paths=None, deleted_paths=None): if saved_paths is None: saved_paths = set() if deleted_paths is None: deleted_paths = set() for model, fields in collector.save.items(): model.resolve_attributes(snapshots=('committed',)) model._stage_changes(fields) for model in collector.delete: path = model.storage_path(model, snapshots=('committed', 'staged', 'working')) if model.opts.owner: if path and path not in saved_paths and path not in deleted_paths: to_save = self._get_object_to_dump( model, parent_snapshots=('committed',)) model.storage.save(path, ContentFile( to_save.dumps(state='staged'), path)) saved_paths.add(path) else: if path not in deleted_paths: try: model.storage.delete(path) except IOError as ex: # Assume missing files are already deleted if ex.errno != errno.ENOENT: raise deleted_paths.add(path) for model, fields in collector.save.items(): model._commit_changes(saved_paths, deleted_paths) for model in collector.delete: store = model.data_store store.update_snapshot('working', ('working', 'staged', 'committed')) store.clear_snapshot('staged') store.clear_snapshot('committed') @classmethod def load(cls, storage, instance=None, **kwargs): if storage is None: return path = cls.storage_path(instance or kwargs, snapshots=('committed', 'working')) if not path: return many = bool(cls.opts.owner) and not cls.opts.single if instance and many: try: instance.data_store.get(instance._pk_field) except KeyError: return if path in cls.loaded.setdefault(storage, set()): return cls.loaded[storage].add(path) if not storage.exists(path): if many: return cls.collection() return instance # may be None file_data = storage.open(path).read() if not cls.opts.raw: try: file_data = file_data.decode('utf-8') except AttributeError: pass file_data = json.loads(file_data, object_pairs_hook=OrderedDict) if cls.opts.polymorphic: if not many: file_data = [file_data] collection_type = cls.__bases__[0] result = collection_type.collection() for polymorphic_data in file_data: polymorphic_type = get_polymorphic_model(polymorphic_data) polymorphic_schema = polymorphic_type._file_model.file_schema result.append( polymorphic_schema( context={'storage': storage}).load( polymorphic_data).data) if len(result) == 1 and not many: result = result[0] return result file_schema = cls._file_model.file_schema result = file_schema( context={'storage': storage, 'path': path}).load( file_data, many=many).data return result @classmethod def storage_path(cls, data, snapshots=None): if isinstance(data, cls): data = data.data_store.accessor(snapshots) else: data = AttributeDict(data) try: path = (cls.opts.path or u'').format(self=data) except AttributeError as e: if cls.opts.ignore_if_missing: return raise PathResolutionError( u"Could not resolve file path for model '{}':\n" u" {}".format(cls.__name__, e)) return path or None def resolve_attributes(self, *attributes, **kwargs): if not self.storage: return file_fields = self._file_fields if not attributes: attributes = file_fields snapshots = kwargs.get('snapshots') if snapshots is None: snapshots = self.snapshots data = self.data_store.accessor(snapshots) try: for attribute in attributes: if (attribute in file_fields and attribute not in self._initializing and not hasattr(data, attribute)): self.load(self.storage, instance=self) break except PathResolutionError: pass def copy(self, new_id=None, storage=None): if new_id is None: new_id = short_guid() field_names = {field: getattr(self, field) for field in self._field_names if field != 'id'} field_names.update({ 'id': new_id, 'storage': storage, }) return self.__class__(**field_names) ================================================ FILE: portia_server/portia_orm/collection.py ================================================ import json from collections import Sequence from .exceptions import ImproperlyConfigured, ValidationError from .snapshots import ModelSnapshots from .utils import ( cached_property, unspecified, validate_type, OrderedIndexedTransformDict ) __all__ = [ 'set_related', 'clear_related', 'FieldCollection', 'ModelCollection', ] def set_related(model, relationship_name, related): current_related_value = getattr(model, relationship_name, None) if isinstance(current_related_value, ModelCollection): current_related_value.add(related) else: setattr(model, relationship_name, related) def clear_related(model, relationship_name, related): current_related_value = getattr(model, relationship_name, None) if isinstance(current_related_value, ModelCollection): current_related_value.discard(related) elif current_related_value == related: setattr(model, relationship_name, None) class OwnedList(list): def __init__(self, iterable=None, owner=None, attrname=None, snapshots=None): super(OwnedList, self).__init__() def get_key(model): try: assert len(model) == 2 return tuple(model) except (AssertionError, TypeError): pass try: return model.data_key except AttributeError: pass if isinstance(model, int): model = next((m for m, v in self.cache._data.items() if v == model), None) if model is not None: return get_key(model) elif isinstance(model, str): return (self.__class__, model) try: return ('start-url', (model['type'], model['url'])) except (TypeError, KeyError): pass raise TypeError('invalid key: {!r}'.format(model)) self.cache = OrderedIndexedTransformDict(get_key) self.owner = owner and owner.with_snapshots() self.attrname = attrname self.snapshots = snapshots or ModelSnapshots.default_snapshots if (owner is None) != (attrname is None): raise ImproperlyConfigured( u"To create a {} connected to an instance both 'instance' and " u"'attrname' must be provided".format( self.__class__.__name__)) if iterable: self.extend(iterable) @cached_property def field(self): return self.owner._fields[self.attrname] def with_snapshots(self, snapshots=None): if self.snapshots == (snapshots or ModelSnapshots.default_snapshots): return self copy = self.__class__(owner=self.owner, attrname=self.attrname, snapshots=snapshots) super(OwnedList, copy).extend(self) return copy def __setitem__(self, index, value): is_slice = isinstance(index, slice) cache = self.cache if is_slice: try: value = list(value) except TypeError: TypeError(u"can only assign an iterable") for v in value: self._validate(v) if v in cache: raise ValueError( u"Collection already contains object {}".format(v)) else: self._validate(value) try: current = self[index] changed = value == current except IndexError: current = None changed = True super(OwnedList, self).__setitem__(index, value) if is_slice: self._populate_cache() else: if current is not None: key = current else: key = next((k for k, v in cache.items() if v == index), None) if key is not None: cache.replace(key, value) if changed: self._update_owner_data() def __delitem__(self, index): super(OwnedList, self).__delitem__(index) del self.cache[index] self._update_owner_data() def __getslice__(self, i, j): return self.__getitem__(slice(i, j)) def __setslice__(self, i, j, value): self.__setitem__(slice(i, j), value) def __delslice__(self, i, j): self.__delitem__(slice(i, j)) def __contains__(self, key): if key in self.cache: return True if len(self.cache) != len(self): try: if self.index(key) > -1: return True except ValueError: pass return False def append(self, value): self._validate(value) super(OwnedList, self).append(value) self.cache[value] = len(self.cache) + 1 self._update_owner_data() def extend(self, iterable): for value in iterable: self.append(value) def insert(self, index, value): self._validate(value) super(OwnedList, self).insert(index, value) self.cache.insert(index, value) self._update_owner_data() def remove(self, value): self._validate(value) super(OwnedList, self).remove(value) self.cache.pop(value, None) self._update_owner_data() def pop(self, index=-1): value = super(OwnedList, self).pop(index) self.cache.pop(value) self._update_owner_data() return value def index(self, value, start=None, stop=None): try: return self.cache[value] except (ValueError, KeyError): if len(self.cache) != len(self): self._populate_cache() if len(self) == len(self.cache): return self.index(value) try: # Try to find matches by checking eq instead of by key return super().index(value) except ValueError: raise ValueError('{!r} is not in {}'.format( value, self.__class__.__name__)) def clear(self): del self[:] self.cache.clear() def _validate(self, value): raise NotImplementedError def _update_owner_data(self): if self.owner: owner = self.owner.with_snapshots(self.snapshots) owner.set_data(self.attrname, self) def _populate_cache(self): self.cache.clear() self.cache.update((k, i) for i, k in enumerate(self)) class FieldCollection(OwnedList): def _validate(self, value): try: self.field.deserialize(value, attr=self.attrname, data=self.owner) except ValidationError: return False return True class ModelCollection(OwnedList): """ A collection of models This is an mutable ordered set that can be indexed by the model's primary key. """ model = None @cached_property def related_name(self): if self.owner is None: return None return self.owner._fields[self.attrname].related_name def __getitem__(self, key): try: return super(ModelCollection, self).__getitem__(key) except TypeError: pass index = self._key_to_index(key) try: return super(ModelCollection, self).__getitem__(index) except TypeError: if not isinstance(key, (int, slice)): raise KeyError(key) raise def __setitem__(self, key, value): index = self._key_to_index(key) current_value = self._get_index(index) if isinstance(index, slice): super(ModelCollection, self).__setitem__( index, (item.with_snapshots() for item in value)) else: super(ModelCollection, self).__setitem__( index, value.with_snapshots()) if current_value != value: self._clear_related(current_value) self._set_related(value) def __delitem__(self, key): index = self._key_to_index(key) current_value = self._get_index(index) super(ModelCollection, self).__delitem__(index) self._clear_related(current_value) def __repr__(self): content_repr = super(ModelCollection, self).__repr__() if self.owner: return u'{}<{}>(owner={!r}){}'.format( self.__class__.__name__, self.snapshots[0], self.owner, content_repr) return u'{}<{}>{}'.format( self.__class__.__name__, self.snapshots[0], content_repr) def append(self, obj): if obj in self: raise ValueError( u"Collection already contains object {}".format(obj)) super(ModelCollection, self).append(obj.with_snapshots()) self._set_related(obj) def add(self, obj): try: self.append(obj) except ValueError: self[obj] = obj def extend(self, iterable): for obj in iterable: self.append(obj) def update(self, iterable): for obj in iterable: self.add(obj) def insert(self, index, obj): if obj in self: raise ValueError( u"Collection already contains object {}".format(obj)) super(ModelCollection, self).insert(index, obj.with_snapshots()) self._set_related(obj) def remove(self, obj): super(ModelCollection, self).remove(obj) self._clear_related(obj) def discard(self, obj): # May still raise a ValidationError for an invalid obj try: self.remove(obj) except ValueError: pass def pop(self, key=unspecified): index = self._key_to_index(key) if index is unspecified: index = -1 try: value = super(ModelCollection, self).pop(index) except IndexError: raise IndexError(u"index not in collection") except TypeError: if not isinstance(key, (int, slice)): raise KeyError(key) raise self._clear_related(value) return value def get(self, key, default=None): index = self._key_to_index(key) return self._get_index(index, default) def keys(self): for model in self: yield model.pk def dump(self, state='working'): try: index = ModelSnapshots.default_snapshots.index(state) except ValueError: raise ValueError(u"'{}' is not a valid state".format(state)) context = { 'snapshots': ModelSnapshots.default_snapshots[index:] } if self.model.opts.polymorphic: return [instance.__class__.file_schema( context=context).dump(instance).data for instance in self] return self.model.file_schema( many=True, context=context).dump(self).data def dumps(self, state='working'): return json.dumps(self.dump(state=state), sort_keys=False, indent=4, separators=(', ', ': ')) def _validate(self, value): validate_type(value, self.model) def _get_index(self, index, default=None): try: return super(ModelCollection, self).__getitem__(index) except (IndexError, TypeError): return default def _key_to_index(self, key): """ Try to find the index at which the key resides. We're using index here instead of a mapping, trading efficiency for avoiding the added complexity of managing changes to the primary_key. May return an invalid index. """ if not isinstance(key, slice): try: if not isinstance(key, self.model): return self.index((self.model, key)) return self.index(key) except ValueError: pass return key def _set_related(self, related): if related and self.owner: if not isinstance(related, list): related = [related] for r in (r.with_snapshots(self.snapshots) for r in related): set_related(r, self.related_name, self.owner) def _clear_related(self, related): if related and self.owner: if not isinstance(related, list): related = [related] for r in (r.with_snapshots(self.snapshots) for r in related): clear_related(r, self.related_name, self.owner) class ListDescriptor(object): def __init__(self, attrname): self.attrname = attrname def __get__(self, instance, instance_type=None): if instance is None: return self try: collection = instance.get_data(self.attrname) except AttributeError: collection = self.new_collection(instance) instance.data_store.set(self.attrname, collection, 'committed') return collection.with_snapshots(instance.snapshots) def __set__(self, instance, values): if not isinstance(values, Sequence): raise ValueError( "You can only assign sequences to '{}'".format(self.attrname)) collection = self.__get__(instance) for value in values: collection._validate(value) if collection != values: self.replace_collection(collection, values) def new_collection(self, instance): return FieldCollection(owner=instance, attrname=self.attrname, snapshots=('committed',)) def replace_collection(self, collection, values): del collection[:] collection.extend(values) ================================================ FILE: portia_server/portia_orm/datastore.py ================================================ from contextlib import contextmanager from threading import local from weakref import WeakKeyDictionary class DataStoreHandler(local): @property def data_store(self): try: return self._data_store except AttributeError: raise RuntimeError( "No data store available, you may need to wrap your code in " "the portia_orm.datastore.data_store_context context manager.") @data_store.setter def data_store(self, value): self._data_store = value @data_store.deleter def data_store(self): delattr(self, '_data_store') @property def loaded(self): try: return self._loaded except AttributeError: raise RuntimeError( "No data store available, you may need to wrap your code in " "the portia_orm.datastore.data_store_context context manager.") @loaded.setter def loaded(self, value): self._loaded = value @loaded.deleter def loaded(self): delattr(self, '_loaded') @contextmanager def data_store_context(): shared_data.data_store = WeakKeyDictionary() shared_data.loaded = WeakKeyDictionary() yield del shared_data.data_store del shared_data.loaded shared_data = DataStoreHandler() ================================================ FILE: portia_server/portia_orm/decorators.py ================================================ from marshmallow.decorators import (validates, validates_schema, pre_dump, post_dump, pre_load, post_load) __all__ = [ 'validates', 'validates_schema', 'pre_dump', 'post_dump', 'pre_load', 'post_load', ] ================================================ FILE: portia_server/portia_orm/deletion.py ================================================ from collections import OrderedDict from .exceptions import ProtectedError from .relationships import HasMany __all__ = [ 'Collector', 'CASCADE', 'CLEAR', 'PROTECT' ] class Collector(set): def __init__(self): super(Collector, self).__init__() self.save = OrderedDict() self.delete = [] def save_instance(self, instance, *fields): if instance in self.delete: return elif instance in self.save: self.save[instance].update(fields) else: self.save[instance] = set(fields) def delete_instance(self, instance): if instance in self.delete: return if instance in self.save: del self.save[instance] self.delete.append(instance) def CASCADE(collector, instance, field_name, related_instance): field = instance._fields[field_name] if isinstance(field, HasMany): getattr(instance, field_name).discard(related_instance) else: setattr(instance, field_name, None) instance._stage_delete(collector) def CLEAR(collector, instance, field_name, related_instance): field = instance._fields[field_name] if isinstance(field, HasMany): getattr(instance, field_name).discard(related_instance) else: setattr(instance, field_name, None) if not field.ignore_in_file: collector.save_instance(instance, field_name) def PROTECT(collector, instance, field_name, related_instance): raise ProtectedError( u"Cannot delete model {} because it is referenced through a " u"protected relationship '{}' of model {}".format( related_instance, field_name, instance)) ================================================ FILE: portia_server/portia_orm/exceptions.py ================================================ from marshmallow.exceptions import ValidationError __all__ = [ 'ImproperlyConfigured', 'ValidationError', ] class ImproperlyConfigured(Exception): pass class PathResolutionError(Exception): pass class ProtectedError(Exception): pass ================================================ FILE: portia_server/portia_orm/fields.py ================================================ import re from marshmallow import fields, Schema, validate from marshmallow.utils import get_value, missing from six import iteritems, itervalues from .collection import ListDescriptor from .deletion import CASCADE, CLEAR, PROTECT from .exceptions import ImproperlyConfigured, ValidationError from .relationships import BelongsTo, HasMany, HasOne from .validators import OneOf __all__ = [ 'Boolean', 'Domain', 'Field', 'List', 'Integer', 'Regexp', 'String', 'Url', 'BelongsTo', 'HasMany', 'HasOne', 'StartUrl', 'CASCADE', 'CLEAR', 'PROTECT', ] class FieldDescriptor(object): """Descriptor for interacting with model fields""" def __init__(self, attrname, field): self.attrname = attrname self.field = field @property def default(self): # may raise an AttributeError if callable(self.field.default): return self.field.default() else: return self.field.default def __get__(self, instance, instance_type=None): if instance is None: return self if instance.has_data(self.attrname): return instance.get_data(self.attrname) default = self.default if default is not missing: # if using default set it on the instance, since it may be # mutable instance.set_data(self.attrname, default) return default raise AttributeError( u"'{}' object has no attribute '{}'".format( instance_type.__name__, self.attrname)) def __set__(self, instance, value): # validate the value against the field self.field.deserialize(value, attr=self.attrname, data=instance) instance.set_data(self.attrname, value) class Field(fields.Field): def __init__(self, **kwargs): ignore_in_file = kwargs.pop('ignore_in_file', False) primary_key = kwargs.pop('primary_key', False) if primary_key: kwargs['required'] = True super(Field, self).__init__(**kwargs) self.primary_key = primary_key self.ignore_in_file = ignore_in_file def contribute_to_class(self, cls, attrname): setattr(cls, attrname, FieldDescriptor(attrname, self)) def get_dependencies(self, cls): if self.primary_key: return set() return {cls._pk_field} def serialize(self, attr, obj, accessor=None): if self._CHECK_ATTRIBUTE: value = self.get_value(attr, obj, accessor=accessor) self._validate_missing(value) self._validate(value) return super(Field, self).serialize(attr, obj, accessor) class ValidatedField(fields.ValidatedField, Field): default_error_messages = { 'invalid': u"Invalid value.", } class Validator(validate.Validator): default_message = u"Invalid value." def __init__(self, error=None): self.error = error or self.default_message def _format_error(self, value): return self.error.format(input=value) def fail(self, value): raise ValidationError(self._format_error(value)) def __call__(self, value): raise NotImplementedError validator = Validator def __init__(self, *args, **kwargs): super(ValidatedField, self).__init__(*args, **kwargs) self.validators.insert(0, self.validator()) def _validated(self, value): self._validate(value) return value class String(fields.String, Field): pass class Boolean(fields.Boolean, Field): pass class Integer(fields.Integer, Field): pass class Url(fields.Url, Field): pass class Domain(ValidatedField, String): default_error_messages = { 'invalid': u"Not a valid domain.", } class ValidDomain(ValidatedField.Validator): # based on marshmallow's Url validator DOMAIN_REGEX = re.compile( r'^' r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+' r'(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... r'localhost|' # localhost... r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|' # ...or ipv4 r'\[?[A-F0-9]*:[A-F0-9:]+\]?)' # ...or ipv6 r'(?::\d+)?' # optional port r'$', re.IGNORECASE) default_message = u"Not a valid domain." def __call__(self, value): if value and self.DOMAIN_REGEX.search(value): return value self.fail(value) validator = ValidDomain class Regexp(ValidatedField, String): default_error_messages = { 'invalid': u"Not a valid regular expression.", } class ValidRegexp(ValidatedField.Validator): default_message = u"Not a valid regular expression." def __call__(self, value): try: re.compile(value) except re.error: self.fail(value) return value validator = ValidRegexp class DependantField(Field): default_error_messages = { 'unknown_condition': u"Value '{value}' for field '{field}' is not " u"supported", } def __init__(self, when, then, **kwargs): for key, field in iteritems(then): if not isinstance(field, Field): raise ImproperlyConfigured( u"Invalid field for the value {!r}".format(key)) super(DependantField, self).__init__(**kwargs) self.when = when self.then = then def get_dependencies(self, cls): return super(DependantField, self).get_dependencies(cls) | {self.when} def serialize(self, attr, obj, accessor=None): field = self._field_for_data(obj) return field.serialize(attr, obj, accessor) def deserialize(self, value, attr=None, data=None): field = self._field_for_data(data) return field.deserialize(value, attr, data) def _add_to_schema(self, field_name, schema): super(DependantField, self)._add_to_schema(field_name, schema) for field in itervalues(self.then): field._add_to_schema(field_name, schema) def _field_for_data(self, data): condition = get_value(self.when, data) try: return self.then[condition] except KeyError: self.fail('unknown_condition', value=condition, field=self.when) class List(fields.List, Field): def contribute_to_class(self, cls, attrname): setattr(cls, attrname, ListDescriptor(attrname=attrname)) class Fragment(ValidatedField, Field): class ValidType(ValidatedField.Validator): default_message = u'The fragment type is not list, range or fixed' def __call__(self, value): if value['type'] in ['list', 'range', 'fixed']: return value self.fail(value) class ValidValue(ValidatedField.Validator): default_message = u"Invalid value for the given fragment type" ALL_LETTERS = r'^[a-zA-Z]+-[a-zA-Z]+$' ALL_NUMBERS = r'^\d+-\d+$' def invalid_range(self, value): all_letters = re.match(self.ALL_LETTERS, value['value']) all_numbers = re.match(self.ALL_NUMBERS, value['value']) return value['type'] == 'range' and not (all_letters or all_numbers) def __call__(self, value): if self.invalid_range(value): self.fail(value) return value def __init__(self, *args, **kwargs): super(Fragment, self).__init__(*args, **kwargs) self.validators = [self.ValidType(), self.ValidValue()] class StartUrl(Schema): fragments = List(Fragment) type = String(validate=OneOf(['url', 'generated', 'feed']), required=True) url = String(default='', required=True) ================================================ FILE: portia_server/portia_orm/middleware.py ================================================ from .datastore import data_store_context class ORMDataStoreMiddleware(object): def __init__(self, get_response=None): self.get_response = get_response def __call__(self, request): with data_store_context(): return self.get_response(request) ================================================ FILE: portia_server/portia_orm/models.py ================================================ from __future__ import unicode_literals import json import re import six from collections import deque, OrderedDict from datetime import datetime from django.conf import settings from marshmallow.fields import Nested from marshmallow.validate import Length from six import iteritems, iterkeys, itervalues from scrapy.utils.misc import load_object from slybot import __version__ as SLYBOT_VERSION from slybot.fieldtypes import FieldTypeManager from slybot.plugins.scrapely_annotations.migration import port_sample from slybot.starturls import StartUrlCollection from slybot.utils import encode from storage.backends import ContentFile from .base import Model from .decorators import pre_load, post_dump from .exceptions import PathResolutionError from .fields import ( Boolean, Domain, Integer, List, Regexp, String, Url, DependantField, BelongsTo, HasMany, HasOne, CASCADE, CLEAR, PROTECT, StartUrl) from .snapshots import ModelSnapshots from .utils import unwrap_envelopes, short_guid, wrap_envelopes, strip_json from .validators import OneOf _CLEAN_ANNOTATED_HTML = re.compile('( data-scrapy-[a-z]+="[^"]+")|' '( data-tagid="\d+")') _ID_RE = re.compile('-'.join(['[a-f0-9]{4}'] * 3), re.I) FIELD_TYPES = FieldTypeManager().available_type_names() class Project(Model): # TODO: override storage for hosted version, return generated project.json id = String(primary_key=True, validate=Length(min=1, max=248)) name = String() schemas = HasMany('Schema', related_name='project', on_delete=CLEAR, ignore_in_file=True) extractors = HasMany('Extractor', related_name='project', on_delete=CLEAR, ignore_in_file=True) spiders = HasMany('Spider', related_name='project', on_delete=CLEAR, ignore_in_file=True) @property def version(self): if self.storage.version_control: return self.storage.commit._id[:7] elif getattr(settings, 'DEPLOY_VERSION', None): return load_object(settings.DEPLOY_VERSION)(self.project) else: return '{:%Y%m%d-%H%M%S}'.format(datetime.now()) class Meta: path = u'project.json' def CASCADE_AUTO_OR_CLEAR(collector, instance, field_name, related_instance): if instance.auto_created: CASCADE(collector, instance, field_name, related_instance) else: CLEAR(collector, instance, field_name, related_instance) class Schema(Model): id = String(primary_key=True) name = String(required=True) auto_created = Boolean(default=False) default = Boolean(default=False) project = BelongsTo(Project, related_name='schemas', on_delete=CASCADE, ignore_in_file=True) items = HasMany('Item', related_name='schema', on_delete=CASCADE_AUTO_OR_CLEAR, ignore_in_file=True) fields = HasMany('Field', related_name='schema', on_delete=CLEAR) class Meta: path = u'items.json' owner = 'project' @pre_load(pass_many=True) def unwrap_envelopes(self, data, many): return unwrap_envelopes(data, many, 'id', True) @pre_load def name_from_id(self, data): if 'name' not in data: data['name'] = data['id'] return data @pre_load def add_fake_items(self, data): data['items'] = [] return data @post_dump def remove_fake_items(self, data): data.pop('items', None) return data @post_dump def remove_auto_created_false(self, data): if 'auto_created' in data and not data['auto_created']: del data['auto_created'] if 'default' in data and not data['default']: del data['default'] return data @post_dump(pass_many=True) def wrap_envelopes(self, data, many): return wrap_envelopes(data, many, 'id', True) class Field(Model): id = String(primary_key=True) name = String(required=True) type = String(required=True, default='text', validate=OneOf(FIELD_TYPES)) required = Boolean(default=False) vary = Boolean(default=False) auto_created = Boolean(default=False) schema = BelongsTo(Schema, related_name='fields', on_delete=CASCADE, ignore_in_file=True) annotations = HasMany('Annotation', related_name='field', on_delete=CASCADE_AUTO_OR_CLEAR, ignore_in_file=True) class Meta: path = u'items.json' owner = 'schema' def __repr__(self): return super(Field, self).__repr__('name', 'type') @pre_load(pass_many=True) def unwrap_envelopes(self, data, many): return unwrap_envelopes(data, many, 'id', False) @pre_load def name_from_id(self, data): if 'name' not in data: data['name'] = data['id'] return data @pre_load def add_fake_annotations(self, data): data['annotations'] = [] return data @post_dump def remove_fake_annotations(self, data): data.pop('annotations', None) return data @post_dump def remove_auto_created_false(self, data): if 'auto_created' in data and not data['auto_created']: del data['auto_created'] return data @post_dump(pass_many=True) def wrap_envelopes(self, data, many): return wrap_envelopes(data, many, 'id', False) class Extractor(Model): id = String(primary_key=True) type = String(required=True, validate=OneOf(['type', 'regex'])) value = DependantField(when='type', then={ 'type': String(required=True, validate=OneOf(FIELD_TYPES)), 'regex': Regexp(required=True), }) project = BelongsTo(Project, related_name='extractors', on_delete=CASCADE, ignore_in_file=True) annotations = HasMany('Annotation', related_name='extractors', on_delete=CLEAR, ignore_in_file=True) class Meta: path = u'extractors.json' owner = 'project' @pre_load(pass_many=True) def unwrap_envelopes(self, data, many): return unwrap_envelopes(data, many, 'id', False) @pre_load def to_type_and_value(self, data): type_extractor = data.pop('type_extractor', None) regular_expression = data.pop('regular_expression', None) if type_extractor: data['type'] = 'type' data['value'] = type_extractor elif regular_expression: data['type'] = 'regex' data['value'] = regular_expression else: data['type'] = 'type' data['value'] = 'text' return data @post_dump def from_type_and_value(self, data): # may be missing if serializing only id if 'type' in data and 'value' in data: type_ = data.pop('type') value = data.pop('value') if type_ == 'type': data['type_extractor'] = value else: # type_ == 'regex' data['regular_expression'] = value return data @post_dump(pass_many=True) def wrap_envelopes(self, data, many): return wrap_envelopes(data, many, 'id', False) class Spider(Model): # TODO: validate id against allowed file name id = String(primary_key=True, validate=Length(min=1, max=243)) start_urls = List(Nested(StartUrl)) links_to_follow = String(default='all', validate=OneOf( ['none', 'patterns', 'all', 'auto'])) allowed_domains = List(Domain) respect_nofollow = Boolean(default=True) follow_patterns = List(Regexp) exclude_patterns = List(Regexp) js_enabled = Boolean(default=False) js_enable_patterns = List(Regexp) js_disable_patterns = List(Regexp) perform_login = Boolean(default=False) login_url = String(default='', allow_none=True) login_user = String(default='', allow_none=True) login_password = String(default='', allow_none=True) project = BelongsTo(Project, related_name='spiders', on_delete=CASCADE, ignore_in_file=True) samples = HasMany('Sample', related_name='spider', on_delete=CLEAR, only='id') class Meta: path = u'spiders/{self.id}.json' def __repr__(self): return super(Spider, self).__repr__('id') @classmethod def load(cls, storage, instance=None, project=None, **kwargs): if instance is None and project: # Load Spiders collection from file listing directories, files = storage.listdir('spiders') return cls.collection( cls(storage, snapshots=('committed',), id=strip_json(filename)).with_snapshots() for filename in files if filename.endswith('.json')) return super(Spider, cls).load( storage, instance, project=project, **kwargs) @pre_load def populate_id(self, data): spider_id = data.get('id') if spider_id and not _ID_RE.match(spider_id): return data path = self.context['path'] data['id'] = strip_json(path.split('/')[-1]) return data @pre_load def dump_templates(self, data): if not data.get('templates'): path = '/'.join(strip_json(self.context['path']).split('/')[:2]) storage = self.context['storage'] try: names = OrderedDict((strip_json(fname), 1) for fname in storage.listdir(path)[1]) data['samples'] = list(names) return data except OSError: # Directory does not exist data['samples'] = [] return data templates = [] for template in data['templates']: # Only migrate item templates if template.get('page_type') != 'item': continue template['id'] = template.get('page_id') or template.get('name') templates.append(template['id']) path = self.context['path'] path = '/'.join((strip_json(path).strip('/'), '{}.json'.format(template['id']))) sample = json.dumps(template, sort_keys=True, indent=4) self.context['storage'].save(path, ContentFile(sample, path)) data['samples'] = templates path, storage = self.context['path'], self.context['storage'] spider = json.dumps(data, indent=4, sort_keys=True) storage.save(path, ContentFile(spider, path)) return data @pre_load def normalize_start_urls(self, data): if 'start_urls' in data or 'generated_urls' in data: start_urls = (data.get('start_urls', []) + data.get('generated_urls', [])) data['start_urls'] = StartUrlCollection(start_urls).normalize() return data @pre_load def get_init_requests(self, data): init_requests = data.pop('init_requests', []) if init_requests: login_request = init_requests[0] if isinstance(login_request, dict): data['login_url'] = login_request.get('loginurl', '') data['login_user'] = login_request.get('username', '') data['login_password'] = login_request.get('password', '') data['perform_login'] = self._is_perform_login(data) return data @post_dump def set_init_requests(self, data): if data.pop('perform_login', None) and self._is_perform_login(data): data['init_requests'] = [OrderedDict([ ('type', 'login'), ('loginurl', data['login_url']), ('username', data['login_user']), ('password', data['login_password']), ])] data.pop('login_url', None) data.pop('login_user', None) data.pop('login_password', None) data.pop('samples', None) return OrderedDict(sorted(iteritems(data))) @staticmethod def _is_perform_login(data): return all(data.get(field) for field in ('login_url', 'login_user', 'login_password')) class OrderedAnnotationsMixin(object): @property def ordered_children(self): children = BaseAnnotation.collection() for annotation in self.annotations: children.append(annotation) if isinstance(annotation, Item): children.extend(annotation.ordered_children) return children @property def ordered_annotations(self): annotations = Annotation.collection() for annotation in self.annotations: if isinstance(annotation, Item): annotations.extend(annotation.ordered_annotations) else: annotations.append(annotation) return annotations @property def ordered_items(self): items = Item.collection() for annotation in self.annotations: if isinstance(annotation, Item): items.append(annotation) items.extend(annotation.ordered_items) return items class Sample(Model, OrderedAnnotationsMixin): id = String(primary_key=True) name = String(required=True) url = Url(required=True) page_id = String(default='') page_type = String(default='item', validate=OneOf(['item'])) items = HasMany('Item', related_name='sample', on_delete=CLEAR) rendered_body = HasOne('RenderedBody', related_name='sample', on_delete=CLEAR, ignore_in_file=True) original_body = HasOne('OriginalBody', related_name='sample', on_delete=CLEAR, ignore_in_file=True) spider = BelongsTo(Spider, related_name='samples', on_delete=CASCADE, only='id') class Meta: path = u'spiders/{self.spider.id}/{self.id}.json' def __repr__(self): return super(Sample, self).__repr__('name', 'url') @property def annotations(self): return self.items @classmethod def load(cls, storage, instance=None, spider=None, **kwargs): if instance is None and spider: # Samples are stored in separate files, but they are listed in the # Spider file. If this gets called, it means that file didn't exist # so return an empty collection return cls.collection() return super(Sample, cls).load( storage, instance, spider=spider, **kwargs) @pre_load def chain_load(self, data): if set(data) == {'id'}: return data methods = (self.migrate_sample, self.get_items) for method in methods: data = method(self, data) return data @staticmethod def migrate_sample(self, data): if not data.get('name'): data['name'] = (data.get('id', data.get('page_id', u'')[:20]) or strip_json(self.context['path'].split('/')[-1])) version = data.get('version', '') if version == '0.13.0' or version >= '0.13.1': return data if any(body in data for body in ('original_body', 'rendered_body')): self._migrate_html(self, data) schemas = json.load(self.context['storage'].open('items.json')) if version >= '0.13.0': return data if 'id' not in data: data['id'] = data['name'] annotations = (data.pop('plugins', {}).get('annotations-plugin', {}) .get('extracts', [])) items = [a for a in annotations if a.get('item_container')] if items: return data extractors = json.load(self.context['storage'].open_with_default( 'extractors.json', {})) sample, new_schemas = port_sample(data, schemas, extractors) self._add_schemas(self, new_schemas) self.save_raw(self, sample) return sample @staticmethod def get_items(self, data): annotations = (data.pop('plugins', {}).get('annotations-plugin', {}) .get('extracts', [])) containers = OrderedDict() items = [] for annotation in annotations: id_ = annotation['id'] if annotation.get('item_container', False): containers[id_] = annotation annotation.update({ 'repeated_selector': None, 'children': [], 'type': 'Item', }) items.append(annotation) else: # split annotations with multiple keys in data for data_id, annotation_data in iteritems( annotation.get('data', {})): items.append(dict(annotation, **{ 'data': { data_id: annotation_data, }, 'type': 'Annotation', })) for item in items: container_id = item.get('container_id') if item.get('repeated') and item.get('item_container'): del item['repeated'] parent = containers.pop(container_id) container_id = item['container_id'] = parent['container_id'] item['repeated_selector'] = item['selector'] item['selector'] = parent['selector'] try: item['siblings'] = parent['siblings'] or item['siblings'] except KeyError: item['siblings'] = 0 item['schema_id'] = parent['schema_id'] or item['schema_id'] if container_id: try: containers[container_id]['children'].remove(parent) except ValueError: pass if container_id: containers[container_id]['children'].append(item) data['items'] = [container for container in itervalues(containers) if container.get('container_id') is None] return data @staticmethod def _add_schemas(serializer, schemas): storage = serializer.context['storage'] project = Project(storage, id=str(storage.name)) schema_collection = project.schemas for schema_id, schema in iteritems(schemas): model = Schema(storage, id=schema_id, project=project, name=schema.get('name', schema_id)) for field_id, field in iteritems(schema['fields']): field.pop('id', None) model.fields.add(Field(storage, id=field_id, schema=model, **field)) schema_collection.add(model) project.schemas = schema_collection @staticmethod def _populate_schema_id(data, schema_id): try: annotations = data['plugins']['annotations-plugin']['extracts'] except KeyError: annotations = [] for anno in annotations: if (anno.get('item_container') and anno.get('container_id') is None and anno.get('schema_id') is None): anno['schema_id'] = schema_id @staticmethod def _migrate_html(self, sample): base_path = strip_json(self.context['path']).strip('/') # Clean and use annotated body if there is no original body present if 'annotation_body' in sample and not sample.get('original_body'): sample['original_body'] = self._clean(sample['annotated_body']) storage = self.context['storage'] for key, value in sample.items(): if (not value or not key.endswith('_body') or key == 'annotated_body'): continue path = '/'.join((base_path, '{}.html'.format(key))) html = value.encode('utf-8') if hasattr(html, 'encode') and isinstance(html, six.text_type): html = encode(html).decode('utf-8') if not storage.exists(path): storage.save(path, ContentFile(html, path)) return sample @post_dump def add_fields(self, data): items = data.pop('items', []) queue = deque(items) output_annotations = [] while queue: annotation = queue.popleft() if annotation.get('item_container'): children = annotation.pop('children', []) repeated_selector = annotation.pop('repeated_selector', None) if repeated_selector: parent_id = '{}#parent'.format(annotation['id']) output_annotations.append(OrderedDict(annotation, **{ 'id': parent_id, 'repeated': False, })) output_annotations.append(OrderedDict(annotation, **{ 'container_id': parent_id, 'repeated': True, 'selector': repeated_selector, })) else: output_annotations.append(annotation) queue.extendleft(reversed(children)) else: output_annotations.append(annotation) scrapes = None for annotation in output_annotations: scrapes = annotation.get('schema_id') if scrapes: break data.update({ 'extractors': data.get('extractors', {}), 'plugins': { 'annotations-plugin': { 'extracts': output_annotations, }, }, 'scrapes': scrapes, 'version': SLYBOT_VERSION, }) return OrderedDict(sorted(iteritems(data))) @staticmethod def save_raw(serializer, data): context = serializer.context path, storage = context['path'], context['storage'] data = {k: v for k, v in data.items() if not k.endswith('_body')} sample = json.dumps(data, indent=4, sort_keys=True) storage.save(path, ContentFile(sample, path)) def clean(self, data): return _CLEAN_ANNOTATED_HTML.sub('', data) class BaseAnnotation(Model): id = String(primary_key=True) parent = BelongsTo('Item', related_name='annotations', on_delete=CASCADE, only='id') class Meta: polymorphic = True class Item(BaseAnnotation, OrderedAnnotationsMixin): name = String(allow_none=True, load_from='field', dump_to='field') selector = String(allow_none=True, default=None) repeated_selector = String(allow_none=True, default=None) siblings = Integer(default=0) sample = BelongsTo(Sample, related_name='items', on_delete=CASCADE, ignore_in_file=True) annotations = HasMany(BaseAnnotation, related_name='parent', polymorphic=True, on_delete=CLEAR, load_from='children', dump_to='children') schema = BelongsTo(Schema, related_name='items', on_delete=PROTECT, load_from='schema_id', dump_to='schema_id', only=('id',)) class Meta: path = u'spiders/{self.sample.spider.id}/{self.sample.id}.json' owner = 'sample' def __repr__(self): return super(Item, self).__repr__('name', 'selector', 'repeated_selector') @property def owner_sample(self): if self.sample: return self.sample if self.parent: return self.parent.owner_sample return None @classmethod def storage_path(cls, data, snapshots=None): # in the nested item case try to get the path from parent try: return super(Item, cls).storage_path(data, snapshots) except PathResolutionError as e: if isinstance(data, cls): try: parent = data.data_store.get('parent', snapshots=snapshots) except KeyError: raise e return cls.storage_path(parent, snapshots) raise e def _get_parent_object(self, parent_snapshots): return self.with_snapshots(parent_snapshots).owner_sample @pre_load def wrap_schema_envelopes(self, data): if 'schema_id' in data: data['schema_id'] = { data['schema_id']: {} } return data @pre_load def remove_attributes(self, data): # remove the unused annotations attribute since it will conflict with # the annotations field which reads from/writes to the children # attribute data.pop('annotations', None) return data @pre_load def add_field(self, data): data.setdefault('field', None) return data @post_dump def add_attributes(self, data): if data.get('field') is None: data.pop('field', None) data.update({ 'annotations': { '#portia-content': '#dummy', }, 'container_id': data.pop('parent', None), 'item_container': True, 'repeated': bool(data.get('repeated_selector')), 'required': [], 'tagid': None, 'text-content': '#portia-content' }) return OrderedDict(sorted(iteritems(data))) @post_dump def remove_type(self, data): data.pop('type') return data @post_dump def unwrap_schema_envelopes(self, data): if 'schema_id' in data: data['schema_id'] = (data['schema_id'] and next(iterkeys(data['schema_id']))) return data class Annotation(BaseAnnotation): attribute = String(default='content') text_content = String(default='content') required = Boolean(default=False) selection_mode = String(default='auto', validate=OneOf( ['auto', 'css', 'xpath'])) selector = String(allow_none=True, default=None) xpath = String(allow_none=True, default=None) accept_selectors = List(String) reject_selectors = List(String) repeated = Boolean(default=False) pre_text = String(allow_none=True, default=None) post_text = String(allow_none=True, default=None) field = BelongsTo(Field, related_name='annotations', on_delete=PROTECT, only=('id',)) extractors = HasMany(Extractor, related_name='annotations', on_delete=PROTECT, only=('id',)) class Meta: path = (u'spiders/{self.parent.sample.spider.id}' u'/{self.parent.sample.id}.json') owner = 'parent' def __repr__(self): return super(Annotation, self).__repr__('attribute', 'selector') @property def owner_sample(self): return self.parent.owner_sample @classmethod def storage_path(cls, data, snapshots=None): # in the nested item case try to get the path from parent try: return super(Annotation, cls).storage_path(data, snapshots) except PathResolutionError as e: if isinstance(data, cls): try: parent = data.data_store.get('parent', snapshots=snapshots) except KeyError: raise e return Item.storage_path(parent, snapshots) raise e @classmethod def generate_pk(cls, storage): data_stores = cls.shared_data_store.get(storage, {}) pk = '{}|{}'.format(short_guid(), short_guid()) while (cls, pk) in data_stores: pk = '{}|{}'.format(short_guid(), short_guid()) return pk @pre_load def get_annotation_data(self, data): # there should only be one key in data['data'], annotations with # multiple data keys are split in the Sample's pre_load data_id, annotation_data = next(iteritems(data['data'])) field = annotation_data['field'] or None if field: field = { field: { 'id': field } } extractors = OrderedDict( (ex, {'id': ex}) for ex in annotation_data['extractors'] or []) data = { 'id': '{}|{}'.format(data['id'], data_id), 'container_id': data['container_id'], 'attribute': annotation_data['attribute'] or 'content', 'text_content': data.get('text-content', 'content'), 'required': annotation_data['required'] or False, 'repeated': data.get('repeated', False), 'selection_mode': data.get('selection_mode') or 'auto', 'selector': data['selector'] or None, 'xpath': data.get('xpath') or None, 'accept_selectors': data['accept_selectors'] or [], 'reject_selectors': data['reject_selectors'] or [], 'pre_text': data.get('pre_text') or None, 'post_text': data.get('post_text') or None, 'field': field, } if extractors: data.update({'extractors': extractors}) return data @post_dump def set_annotation_data(self, data): annotation_id, data_id = data['id'].split('|') return OrderedDict([ ('accept_selectors', data['accept_selectors']), ('container_id', data['parent']), ('data', { data_id: OrderedDict([ ('attribute', data['attribute']), ('extractors', list(iterkeys(data['extractors'])) or {}), ('field', data['field'] and next(iterkeys(data['field']))), ('required', data['required']), ]), }), ('id', annotation_id), ('text-content', data['text_content']), ('post_text', data['post_text']), ('pre_text', data['pre_text']), ('reject_selectors', data['reject_selectors']), ('required', []), ('repeated', data['repeated']), ('selection_mode', data['selection_mode']), ('selector', data['selector']), ('tagid', None), ('xpath', data['xpath']), ]) class OriginalBody(Model): id = String(primary_key=True) html = String(default='') sample = BelongsTo(Sample, related_name='original_body', on_delete=CASCADE, ignore_in_file=True) @classmethod def load(cls, storage, instance=None, sample=None, **kwargs): if sample: sample.spider html = super(OriginalBody, cls).load( storage, instance, sample=sample, **kwargs) if (html and not html.sample) and sample: html.sample = sample return html @pre_load def populate_item(self, data): split_path = self.context['path'].split('/') sample_id = split_path[2] if len(split_path) == 3 and sample_id.endswith('.json'): sample_id = strip_json(sample_id) name = self.Meta.name return { 'id': '{}_{}'.format(sample_id, name), 'html': data, } @post_dump def return_html(self, data): return data['html'] def dump(self, state='working'): try: index = ModelSnapshots.default_snapshots.index(state) except ValueError: raise ValueError(u"'{}' is not a valid state".format(state)) context = { 'snapshots': ModelSnapshots.default_snapshots[index:] } return self.file_schema(context=context).dump(self).data def dumps(self, state='working'): return self.dump(state=state) class Meta: raw = True single = True path = (u'spiders/{self.sample.spider.id}/{self.sample.id}/' u'original_body.html') name = 'original_body' class RenderedBody(Model): id = String(primary_key=True) html = String(default='') sample = BelongsTo(Sample, related_name='rendered_body', on_delete=CASCADE, ignore_in_file=True) @classmethod def load(cls, storage, instance=None, sample=None, **kwargs): html = super(RenderedBody, cls).load( storage, instance, sample=sample, **kwargs) if (html and not html.sample) and sample: html.sample = sample return html @pre_load def populate_item(self, data): split_path = self.context['path'].split('/') sample_id = split_path[2] if len(split_path) == 3 and sample_id.endswith('.json'): sample_id = strip_json(sample_id) name = self.Meta.name return { 'id': '{}_{}'.format(sample_id, name), 'html': data, } @post_dump def return_html(self, data): return data['html'] def dump(self, state='working'): try: index = ModelSnapshots.default_snapshots.index(state) except ValueError: raise ValueError(u"'{}' is not a valid state".format(state)) context = { 'snapshots': ModelSnapshots.default_snapshots[index:] } return self.file_schema(context=context).dump(self).data def dumps(self, state='working'): return self.dump(state=state) class Meta: raw = True single = True ignore_if_missing = True path = (u'spiders/{self.sample.spider.id}/{self.sample.id}/' u'rendered_body.html') name = 'rendered_body' ================================================ FILE: portia_server/portia_orm/registry.py ================================================ from six import itervalues from .exceptions import ImproperlyConfigured __all__ = [ 'get_model', 'get_polymorphic_model', ] models = {} def get_model(model_name): try: return models[model_name] except KeyError: raise ImproperlyConfigured( u"No model named '{}' exists".format(model_name)) def get_polymorphic_model(data): for model in itervalues(models): polymorphic = model.opts.polymorphic if polymorphic: polymorphic_key = polymorphic if isinstance(polymorphic_key, bool): polymorphic_key = 'type' if data.get(polymorphic_key) == model.__name__: return model raise ImproperlyConfigured( u"No model found for data: {!r}".format(data)) ================================================ FILE: portia_server/portia_orm/relationships.py ================================================ from collections import Mapping from marshmallow import fields, utils from six import string_types from .collection import set_related, clear_related, ListDescriptor from .exceptions import ImproperlyConfigured, ValidationError from .registry import get_model, get_polymorphic_model from .utils import cached_property, cached_property_ignore_set, validate_type __all__ = [ 'BelongsTo', 'HasMany', 'HasOne' ] class BaseRelationshipDescriptor(object): """Descriptor for interacting with model relationships""" def __init__(self, model, attrname, related_name): self._model = model self.attrname = attrname self.related_name = related_name def __get__(self, instance, instance_type=None): raise NotImplementedError def __set__(self, instance, value): raise AttributeError def __repr__(self): return '{}({}, attrname={!r}, related_name={!r})'.format( self.__class__.__name__, self.model.__name__, self.attrname, self.related_name) @cached_property def model(self): if isinstance(self._model, string_types): self._model = get_model(self._model) return self._model def _validate(self, value): if value is not None: validate_type(value, self.model) class BelongsToDescriptor(BaseRelationshipDescriptor): def __get__(self, instance, instance_type=None): if instance is None: return self return instance.get_data(self.attrname, None) def __set__(self, instance, value): self._validate(value) current_value = self.__get__(instance) if value != current_value: instance.set_data(self.attrname, value and value.with_snapshots()) if current_value: current_value = current_value.with_snapshots(instance.snapshots) clear_related(current_value, self.related_name, instance) if value: value = value.with_snapshots(instance.snapshots) set_related(value, self.related_name, instance) class HasManyDescriptor(ListDescriptor, BaseRelationshipDescriptor): def __init__(self, *args, **kwargs): BaseRelationshipDescriptor.__init__(self, *args, **kwargs) def new_collection(self, instance): # if we got here then the collection could not be loaded from instance's # file, so we load it through the related model model = self.model collection = model.collection( owner=instance, attrname=self.attrname, snapshots=('committed',)) if (self.attrname not in instance._initializing and model.opts.owner in {self.related_name, False}): items = model.load(instance.storage, **{ self.related_name: instance }) if isinstance(items, model.collection) and items: collection.extend(items) return collection def replace_collection(self, collection, values): del collection[:] collection.update(values) class HasOneDescriptor(BelongsToDescriptor): def __get__(self, instance, instance_type=None): try: field = super(HasOneDescriptor, self).__get__(instance, instance_type) assert field is not None except (AttributeError, AssertionError): field = self.model.load(instance.storage, **{ self.related_name: instance }) if field and not getattr(field, self.related_name, None): setattr(field, self.related_name, instance) instance.data_store.set(self.attrname, field, 'committed') return field class BaseRelationship(fields.Nested): descriptor_class = None def __init__(self, model, related_name, on_delete, ignore_in_file=False, polymorphic=False, **kwargs): self._model = model self.related_name = related_name if not callable(on_delete): raise ImproperlyConfigured( u"The on_delete property of a relationship must be a callable") self.on_delete = on_delete self.ignore_in_file = ignore_in_file self.polymorphic = polymorphic super(BaseRelationship, self).__init__(None, **kwargs) if polymorphic and isinstance(self.only, string_types): self.only = (self.only,) @cached_property def model(self): if isinstance(self._model, string_types): self._model = get_model(self._model) return self._model @cached_property_ignore_set def nested(self): return self.model.file_schema @cached_property def schema(self): return super(BaseRelationship, self).schema def _serialize(self, nested_obj, attr, obj): if self.polymorphic: objects = nested_obj if not self.many: objects = [nested_obj] result = [] for polymorphic_object in objects: polymorphic_relationship = self._get_field_for_polymorphic( polymorphic_object.__class__) result.append( polymorphic_relationship._serialize( polymorphic_object, attr, obj)) if len(result) == 1 and not self.many: result = result[0] return result return super(BaseRelationship, self)._serialize(nested_obj, attr, obj) def _deserialize(self, value, attr, data): if self.polymorphic: serialized = value if not self.many: serialized = [value] result = [] for polymorphic_serialized in serialized: polymorphic_type = get_polymorphic_model(polymorphic_serialized) polymorphic_relationship = self._get_field_for_polymorphic( polymorphic_type) result.append( polymorphic_relationship._deserialize( polymorphic_serialized, attr, data)) if len(result) == 1 and not self.many: result = result[0] return result if self.many and not self._is_collection(value): self.fail('type', input=value, type=value.__class__.__name__) data, errors = self.schema.load(value) if errors: raise ValidationError(errors, data=data) return data def _get_field_for_polymorphic(self, model): relationship_copy = object.__new__(self.__class__) relationship_copy.__dict__ = dict(self.__dict__) relationship_copy.__dict__.pop('model', None) relationship_copy.__dict__.pop('nested', None) relationship_copy.__dict__.pop('schema', None) relationship_copy.model = model relationship_copy.many = False relationship_copy.polymorphic = False return relationship_copy def _is_collection(self, value): return isinstance(value, Mapping) or utils.is_collection(value) def contribute_to_class(self, cls, attrname): if (not self.ignore_in_file and not isinstance(self._model, string_types)): if self.related_name not in self._model._fields: raise ImproperlyConfigured( u"Model '{}' has not declared field '{}'".format( self._model.__name__, self.related_name)) related_field = self._model._fields[self.related_name] if related_field.related_name != attrname: raise ImproperlyConfigured( u"Related name of Model '{}' field '{}' is not '{}'".format( self._model.__name__, self.related_name, attrname)) class_includes_relationships = \ self._includes_relationships(self, self._model) related_includes_relationships = \ (not related_field.ignore_in_file and self._includes_relationships(related_field, cls)) if class_includes_relationships and related_includes_relationships: raise ImproperlyConfigured( u"Related fields '{}' of model '{}' and " u"'{}' of model '{}' cannot both include relationships. " u"Use ignore_in_file or only to limit the fields on one " u"side of the relationship.".format( attrname, cls.__name__, self.related_name, self._model.__name__)) descriptor = self.descriptor_class( self._model, attrname=attrname, related_name=self.related_name) setattr(cls, attrname, descriptor) def get_dependencies(self, cls): return {cls._pk_field} @staticmethod def _includes_relationships(field, model): includes_relationships = True if field.only: includes_relationships = False for field in ([field.only] if isinstance(field.only, string_types) else field.only): if isinstance(model._fields[field], BaseRelationship): includes_relationships = True return includes_relationships class BelongsTo(BaseRelationship): descriptor_class = BelongsToDescriptor class HasMany(BaseRelationship): descriptor_class = HasManyDescriptor def __init__(self, *args, **kwargs): kwargs['many'] = True super(HasMany, self).__init__(*args, **kwargs) class HasOne(BaseRelationship): descriptor_class = HasOneDescriptor ================================================ FILE: portia_server/portia_orm/serializers.py ================================================ from collections import OrderedDict, Sequence from marshmallow import schema from six import iteritems, string_types from .decorators import pre_dump, post_dump, post_load __all__ = [ 'FileSerializer', ] class FileSerializerOpts(schema.SchemaOpts): def __init__(self, meta): super(FileSerializerOpts, self).__init__(meta) if meta is schema.BaseSchema.Meta: return self.strict = True # make marshmallow use OrderedDicts, so that collections of enveloped # objects maintain their order when loaded self.ordered = True # the model from which the Schema was created, required self.model = getattr(meta, 'model') self.polymorphic = getattr(meta, 'polymorphic', False) # whether to include the model name in the serialized output, if a # string use that as the output attribute, otherwise uses 'type' if not isinstance(self.polymorphic, (bool, string_types)): raise ValueError( "'polymorphic' option must be a string or boolean.") class FileSerializer(schema.Schema): OPTIONS_CLASS = FileSerializerOpts def __init__(self, *args, **kwargs): super(FileSerializer, self).__init__(*args, **kwargs) if self.opts.polymorphic: self.extra = self.extra or {} polymorphic_key = self.opts.polymorphic if isinstance(polymorphic_key, bool): polymorphic_key = 'type' self.extra[polymorphic_key] = self.opts.model.__name__ def __getattr__(self, item): # try to resolve missing attributes from the model return getattr(self.opts.model, item) def get_attribute(self, attr, obj, default): return super(FileSerializer, self).get_attribute(attr, obj, default) @post_load def create_object(self, data): storage = self.context.get('storage', None) model = self.opts.model(storage, snapshots=('committed',), **data) return model.with_snapshots() @pre_dump def select_snapshots(self, instance): snapshots = self.context.get('snapshots', None) if snapshots is not None: instance = instance.with_snapshots(snapshots) return instance @post_dump def order_keys(self, data): """ Create ordered dictionaries sorted by key. We do this here instead of using the sort_keys parameter of json.dumps, so that object keys are sorted, while collections can maintain their insertion order """ return OrderedDict((item for item in sorted(iteritems(data)))) def _do_load(self, data, many=None, *args, **kwargs): # support the case where we have only a single field to load and we get # it directly rather than wrapped in a dict. this happens when loading # a relationship with a single field in 'only' many = self.many if many is None else bool(many) if not many: data = self._wrap_only(data) elif isinstance(data, Sequence): data = [self._wrap_only(value) for value in data] result, errors = super(FileSerializer, self)._do_load( data, many, *args, **kwargs) # we need to wrap the result of a many load in a ModelCollection, but # post_load(pass_many=True) processors are called before the Model # instances are created in the post_load(pass_many=False) processor if many: result = self.opts.model.collection(result) return result, errors def _wrap_only(self, data): if self.only and len(self.only) == 1 and not isinstance(data, dict): data = { # only can be an OrderedSet which doesn't support indexing next(iter(self.only)): data } return data ================================================ FILE: portia_server/portia_orm/snapshots.py ================================================ from collections import defaultdict __all__ = [ 'ModelSnapshots', ] class ModelSnapshots(defaultdict): default_snapshots = ('working', 'staged', 'committed') class ModelSnapshotsAccessor(object): __slots__ = ['instance', 'snapshots'] def __init__(self, instance, snapshots=None): self.instance = instance self.snapshots = snapshots or ModelSnapshots.default_snapshots def __getattr__(self, name): try: snapshots = self.snapshots value = self.instance.get(name, snapshots) try: value = value.data_store.accessor(snapshots) except AttributeError: pass return value except KeyError: raise AttributeError( u"'{}' object has no attribute '{}'".format( self.__class__.__name__, name)) def __setattr__(self, name, value): if name in self.__slots__: super().__setattr__(name, value) return self.instance.set(name, value, self.snapshots[0]) def __init__(self): super().__init__(dict) def get(self, key, snapshots=None): if not snapshots: snapshots = self.default_snapshots for snapshot in snapshots: try: return self[snapshot][key] except KeyError: pass raise KeyError(repr(key)) def set(self, key, value, snapshot=None): if not snapshot: snapshot = self.default_snapshots[0] self[snapshot][key] = value def copy_from(self, other): assert isinstance(other, ModelSnapshots) for key, snapshot in other.items(): self[key].update(snapshot) def dirty_fields(self, changed, original): dirty = set() for field, value in self[changed].items(): try: if self.get(field, snapshots=original) == value: continue except KeyError: pass dirty.add(field) return dirty def update_snapshot(self, destination, snapshots, fields=None): if fields is None: fields = set() for snapshot in snapshots: fields.update(self[snapshot].keys()) self[destination].update({k: self.get(k, snapshots) for k in fields}) def clear_snapshot(self, snapshot, fields=None): if fields is not None: data = self[snapshot] for field in fields: del data[field] else: del self[snapshot] def accessor(self, snapshots=None): return self.ModelSnapshotsAccessor(self, snapshots) ================================================ FILE: portia_server/portia_orm/tests/__init__.py ================================================ ================================================ FILE: portia_server/portia_orm/tests/models.py ================================================ from .. import fields from ..base import Model class ExampleModel(Model): id = fields.String(primary_key=True) field = fields.Boolean() class RequiredFieldModel(Model): id = fields.String(primary_key=True) field = fields.Field(required=True) class SingleFileModel(Model): id = fields.String(primary_key=True) field = fields.Field() class Meta: path = u'single.json' class ManyFileModel(Model): id = fields.String(primary_key=True) field = fields.Field() owner = fields.BelongsTo('ManyFileModel', related_name='owner', on_delete=fields.CLEAR, ignore_in_file=True) class Meta: path = u'many.json' owner = 'owner' class ParamFileModel(Model): id = fields.String(primary_key=True) field = fields.Field() param = fields.String() class Meta: path = u'param-{self.param}.json' class OneToOneModel1(Model): id = fields.String(primary_key=True) field = fields.Field() m2 = fields.BelongsTo('OneToOneModel2', related_name='m1', on_delete=fields.CLEAR, only='id') class Meta: path = u'o2o-model-1.json' class OneToOneModel2(Model): id = fields.String(primary_key=True) field = fields.Field() m1 = fields.BelongsTo(OneToOneModel1, related_name='m2', on_delete=fields.CLEAR) class Meta: path = u'o2o-model-2.json' class ChildModel(Model): id = fields.String(primary_key=True) field = fields.Field() parent = fields.BelongsTo('ParentModel', related_name='children', on_delete=fields.CLEAR, only='id') class Meta: path = u'{self.parent.id}/children.json' owner = 'parent' class ParentModel(Model): id = fields.String(primary_key=True) field = fields.Field() children = fields.HasMany(ChildModel, related_name='parent', on_delete=fields.CLEAR) class Meta: path = u'parents.json' class ManyToManyModel1(Model): id = fields.String(primary_key=True) field = fields.Field() m2 = fields.HasMany('ManyToManyModel2', related_name='m1', on_delete=fields.CLEAR, only='id') class Meta: path = u'm2m-model-1.json' class ManyToManyModel2(Model): id = fields.String(primary_key=True) field = fields.Field() m1 = fields.HasMany(ManyToManyModel1, related_name='m2', on_delete=fields.CLEAR) class Meta: path = u'm2m-model-2.json' owner = 'm1' class PolymorphicParentModel(Model): id = fields.String(primary_key=True) field = fields.Field() children = fields.HasMany('PolymorphicChildBase', related_name='parent', polymorphic=True, on_delete=fields.CASCADE, only='id') class Meta: path = u'parents.json' class PolymorphicChildBase(Model): id = fields.String(primary_key=True) parent = fields.BelongsTo(PolymorphicParentModel, related_name='children', on_delete=fields.CLEAR, only='id') class Meta: path = u'children.json' owner = 'parent' polymorphic = True class PolymorphicChildModel1(PolymorphicChildBase): field1 = fields.Field() class PolymorphicChildModel2(PolymorphicChildBase): field2 = fields.Field() class Meta: polymorphic = '_type_' ================================================ FILE: portia_server/portia_orm/tests/test_basic.py ================================================ from unittest import mock from .models import (ExampleModel, RequiredFieldModel, SingleFileModel, ManyFileModel, ParamFileModel, PolymorphicChildModel1) from .utils import DataStoreTestCase, mock_storage from ..exceptions import PathResolutionError, ValidationError class BasicModelTests(DataStoreTestCase): def setUp(self): super(BasicModelTests, self).setUp() self.storage = mock_storage({ 'single.json': '{' ' "id": "model-1",' ' "field": true' '}', 'many.json': '[' ' {' ' "id": "model-1",' ' "field": true' ' },' ' {' ' "id": "model-2",' ' "field": false' ' }' ']', 'param-test.json': '{' ' "id": "model-1",' ' "field": false,' ' "param": "test"' '}', }) def test_validation(self): model = ExampleModel(id='model-1') with self.assertRaises(AttributeError): model.field try: model.field = True except ValidationError: self.fail("Assigning to the field attribute failed validation") try: model.field except AttributeError: self.fail("Reading the field attribute failed") with self.assertRaises(ValidationError): model.id = 1 def test_dump(self): model = ExampleModel(id='model-2', field=False) self.assertEqual(model.dump(), { 'id': 'model-2', 'field': False, }) def test_dumps(self): model = ExampleModel(id='model-2', field=False) # Object keys should be sorted self.assertEqual( model.dumps(), '{\n' ' "field": false, \n' ' "id": "model-2"\n' '}') def test_required(self): model = RequiredFieldModel(id='model-1') with self.assertRaises(ValidationError): model.dump() model.field = True try: model.dump() except ValidationError: self.fail("Dump failed validation") def test_load_single(self): model = SingleFileModel.load(self.storage) self.storage.open.assert_called_once_with('single.json') self.assertEqual(model.dump(), { 'id': 'model-1', 'field': True, }) def test_load_single_on_access(self): model = SingleFileModel(self.storage, id='model-1') self.storage.open.assert_not_called() self.assertEqual(model.dump(), { 'id': 'model-1', 'field': True, }) self.storage.open.assert_called_once_with('single.json') def test_partial_load_single(self): model = SingleFileModel(self.storage, id='model-1') self.assertEqual(model.id, 'model-1') self.storage.open.assert_not_called() self.assertEqual(model.field, True) self.storage.open.assert_called_once_with('single.json') self.assertEqual(model.dump(), { 'id': 'model-1', 'field': True, }) self.storage.open.assert_called_once_with('single.json') def test_load_many(self): models = ManyFileModel.load(self.storage) self.storage.open.assert_called_once_with('many.json') self.assertEqual(models.dump(), [ { 'id': 'model-1', 'field': True, }, { 'id': 'model-2', 'field': False, }, ]) def test_load_one_from_many(self): model = ManyFileModel(self.storage, id='model-1') self.assertEqual(model.id, 'model-1') self.storage.open.assert_not_called() self.assertEqual(model.field, True) self.storage.open.assert_called_once_with('many.json') self.assertEqual(model.dump(), { 'id': 'model-1', 'field': True, }) self.storage.open.assert_called_once_with('many.json') def test_load_param(self): model = ParamFileModel(self.storage, id='model-1', param='test') self.assertEqual(model.id, 'model-1') self.storage.open.assert_not_called() self.assertEqual(model.field, False) self.storage.open.assert_called_once_with('param-test.json') self.assertEqual(model.dump(), { 'id': 'model-1', 'field': False, 'param': 'test', }) self.storage.open.assert_called_once_with('param-test.json') def test_load_param_skipped_if_param_missing(self): model = ParamFileModel(self.storage, id='model-1') with self.assertRaises(AttributeError): model.field self.storage.open.assert_not_called() def test_save_single(self): model = SingleFileModel.load(self.storage) model.id = 'changed-id' model.field = False model.save() self.storage.save.assert_called_once_with('single.json', mock.ANY) self.assertEqual( self.storage.files['single.json'], '{\n' ' "field": false, \n' ' "id": "changed-id"\n' '}') def test_save_single_does_not_save_if_nothing_changed(self): model = SingleFileModel.load(self.storage) model.field = True model.save() self.storage.save.assert_not_called() def test_partial_save_single(self): model = SingleFileModel(self.storage, id='model-1') model.id = 'changed-id' self.storage.open.assert_not_called() model.save() self.storage.open.assert_called_once_with('single.json') self.storage.save.assert_called_once_with('single.json', mock.ANY) self.assertEqual( self.storage.files['single.json'], '{\n' ' "field": true, \n' ' "id": "changed-id"\n' '}') def test_save_param(self): model = ParamFileModel(self.storage, id='model-1', param='test') model.field = True model.save() self.storage.save.assert_called_once_with('param-test.json', mock.ANY) self.assertEqual( self.storage.files['param-test.json'], '{\n' ' "field": true, \n' ' "id": "model-1", \n' ' "param": "test"\n' '}') def test_save_param_raises_error_if_params_missing(self): model = ParamFileModel(self.storage, id='model-1') model.field = True with self.assertRaises(PathResolutionError): model.save() self.storage.save.assert_not_called() def test_save_selected_fields(self): model = SingleFileModel.load(self.storage) model.id = 'changed-id' model.field = False model.save(only=['field']) self.storage.save.assert_called_once_with('single.json', mock.ANY) self.assertEqual( self.storage.files['single.json'], '{\n' ' "field": false, \n' ' "id": "model-1"\n' '}') def test_copy(self): model = SingleFileModel.load(self.storage) copied_model = model.copy('new_id') self.assertEqual(model.field, copied_model.field) self.assertNotEqual(model.id, copied_model.id) class PolymorphicModelTests(DataStoreTestCase): def setUp(self): super(PolymorphicModelTests, self).setUp() self.storage = mock_storage({ 'children.json': '[' ' {' ' "type": "PolymorphicChildModel1",' ' "id": "child-1",' ' "field1": "child-1",' ' "parent": "parent-1"' ' },' ' {' ' "_type_": "PolymorphicChildModel2",' ' "id": "child-2",' ' "field2": "child-2",' ' "parent": "parent-1"' ' }' ']', }) def test_load_many(self): models = PolymorphicChildModel1.load(self.storage) self.storage.open.assert_called_once_with('children.json') self.assertEqual(models.dump(), [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', 'field1': 'child-1', 'parent': 'parent-1', }, { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', 'field2': 'child-2', 'parent': 'parent-1', }, ]) def test_load_one_from_many(self): model = PolymorphicChildModel1(self.storage, id='child-1') self.assertEqual(model.id, 'child-1') self.storage.open.assert_not_called() self.assertEqual(model.field1, 'child-1') self.storage.open.assert_called_once_with('children.json') self.assertEqual(model.dump(), { 'type': 'PolymorphicChildModel1', 'id': 'child-1', 'field1': 'child-1', 'parent': 'parent-1', }) self.storage.open.assert_called_once_with('children.json') def test_save_many(self): model = PolymorphicChildModel1(self.storage, id='child-1') model.field1 = 'test' model.save() self.storage.save.assert_called_once_with('children.json', mock.ANY) self.assertEqual( self.storage.files['children.json'], '[\n' ' {\n' ' "field1": "test", \n' ' "id": "child-1", \n' ' "parent": "parent-1", \n' ' "type": "PolymorphicChildModel1"\n' ' }, \n' ' {\n' ' "_type_": "PolymorphicChildModel2", \n' ' "field2": "child-2", \n' ' "id": "child-2", \n' ' "parent": "parent-1"\n' ' }\n' ']') ================================================ FILE: portia_server/portia_orm/tests/test_collection.py ================================================ from .models import (ExampleModel, ChildModel, PolymorphicChildBase, PolymorphicChildModel1, PolymorphicChildModel2) from .utils import DataStoreTestCase from ..exceptions import ValidationError class ModelCollectionTests(DataStoreTestCase): def test_create_(self): collection = ExampleModel.collection() self.assertEqual(len(collection), 0) self.assertListEqual(collection, []) def test_create_with_model(self): model = ExampleModel(id='model-1', field=False) collection = ExampleModel.collection([model]) self.assertEqual(len(collection), 1) self.assertListEqual(collection, [model]) def test_getitem(self): model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) collection = ExampleModel.collection([model1]) self.assertEqual(collection[0], model1) self.assertEqual(collection['model-1'], model1) self.assertEqual(collection[model1], model1) self.assertEqual(collection[model1b], model1) with self.assertRaises(IndexError): collection[1] with self.assertRaises(KeyError): collection['model-2'] with self.assertRaises(KeyError): collection[model2] def test_setitem_index(self): model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) collection = ExampleModel.collection([model1]) collection[0] = model1b self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model1b) self.assertEqual(collection['model-1'], model1b) self.assertEqual(collection[model1], model1b) self.assertEqual(collection[model1b], model1b) collection[0] = model2 self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model2) self.assertEqual(collection['model-2'], model2) self.assertEqual(collection[model2], model2) with self.assertRaises(KeyError): collection['model-1'] with self.assertRaises(KeyError): collection[model1] with self.assertRaises(KeyError): collection[model1b] def test_setitem_key(self): model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) collection = ExampleModel.collection([model1]) collection['model-1'] = model1b self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model1b) self.assertEqual(collection['model-1'], model1b) self.assertEqual(collection[model1], model1b) self.assertEqual(collection[model1b], model1b) collection['model-1'] = model2 self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model2) self.assertEqual(collection['model-2'], model2) self.assertEqual(collection[model2], model2) with self.assertRaises(KeyError): collection['model-1'] with self.assertRaises(KeyError): collection[model1] with self.assertRaises(KeyError): collection[model1b] def test_setitem_object(self): model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) collection = ExampleModel.collection([model1]) collection[model1] = model1b self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model1b) self.assertEqual(collection['model-1'], model1b) self.assertEqual(collection[model1], model1b) self.assertEqual(collection[model1b], model1b) collection[model1] = model2 self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model2) self.assertEqual(collection['model-2'], model2) self.assertEqual(collection[model2], model2) with self.assertRaises(KeyError): collection['model-1'] with self.assertRaises(KeyError): collection[model1] with self.assertRaises(KeyError): collection[model1b] def test_delitem_index(self): model1 = ExampleModel(id='model-1', field=False) model2 = ExampleModel(id='model-2', field=False) model3 = ExampleModel(id='model-3', field=False) collection = ExampleModel.collection([model1, model2, model3]) del collection[1] self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) def test_delitem_key(self): model1 = ExampleModel(id='model-1', field=False) model2 = ExampleModel(id='model-2', field=False) model3 = ExampleModel(id='model-3', field=False) collection = ExampleModel.collection([model1, model2, model3]) del collection['model-2'] self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) def test_delitem_object(self): model1 = ExampleModel(id='model-1', field=False) model2 = ExampleModel(id='model-2', field=False) model3 = ExampleModel(id='model-3', field=False) collection = ExampleModel.collection([model1, model2, model3]) del collection[model2] self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) def test_append(self): collection = ExampleModel.collection() model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) self.assertEqual(len(collection), 0) collection.append(model1) self.assertEqual(len(collection), 1) self.assertListEqual(collection, [model1]) collection.append(model2) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model2]) with self.assertRaises(ValueError): collection.append(model1b) def test_add(self): collection = ExampleModel.collection() model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) self.assertEqual(len(collection), 0) collection.add(model1) self.assertEqual(len(collection), 1) self.assertListEqual(collection, [model1]) collection.add(model2) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model2]) collection.add(model1b) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1b, model2]) def test_extend(self): collection = ExampleModel.collection() model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) self.assertEqual(len(collection), 0) collection.extend([model1, model2]) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model2]) with self.assertRaises(ValueError): collection.extend([model1b]) collection = ExampleModel.collection() with self.assertRaises(ValueError): collection.extend([model1, model2, model1b]) def test_update(self): collection = ExampleModel.collection() model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) self.assertEqual(len(collection), 0) collection.update([model1, model2]) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model2]) collection.update([model2, model1b]) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1b, model2]) def test_insert(self): model1 = ExampleModel(id='model-1', field=False) model2 = ExampleModel(id='model-2', field=False) model3 = ExampleModel(id='model-3', field=False) model4 = ExampleModel(id='model-4', field=False) model5 = ExampleModel(id='model-5', field=False) collection = ExampleModel.collection([model1, model2]) collection.insert(1, model3) self.assertEqual(len(collection), 3) self.assertListEqual(collection, [model1, model3, model2]) collection.insert(0, model4) self.assertEqual(len(collection), 4) self.assertListEqual(collection, [model4, model1, model3, model2]) with self.assertRaises(TypeError): collection.insert('model-2', model5) collection.insert(1000, model5) self.assertEqual(len(collection), 5) self.assertListEqual( collection, [model4, model1, model3, model2, model5]) # items in collection must be unique with self.assertRaises(ValueError): collection.insert(0, model2) def test_remove(self): model1 = ExampleModel(id='model-1', field=False) model2 = ExampleModel(id='model-2', field=False) model3 = ExampleModel(id='model-3', field=False) model4 = ExampleModel(id='model-4', field=False) collection = ExampleModel.collection([model1, model2, model3]) collection.remove(model2) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) with self.assertRaises(ValueError): collection.remove(model4) with self.assertRaises(ValidationError): collection.remove('model-2') def test_discard(self): model1 = ExampleModel(id='model-1', field=False) model2 = ExampleModel(id='model-2', field=False) model3 = ExampleModel(id='model-3', field=False) model4 = ExampleModel(id='model-4', field=False) collection = ExampleModel.collection([model1, model2, model3]) collection.discard(model2) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) collection.discard(model4) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) with self.assertRaises(ValidationError): collection.discard('model-2') def test_pop(self): model1 = ExampleModel(id='model-1', field=False) model2 = ExampleModel(id='model-2', field=False) model3 = ExampleModel(id='model-3', field=False) model4 = ExampleModel(id='model-4', field=False) model5 = ExampleModel(id='model-5', field=False) collection = ExampleModel.collection( [model1, model2, model3, model4, model5]) self.assertEqual(collection.pop(), model5) self.assertEqual(len(collection), 4) self.assertListEqual(collection, [model1, model2, model3, model4]) self.assertEqual(collection.pop(2), model3) self.assertEqual(len(collection), 3) self.assertListEqual(collection, [model1, model2, model4]) with self.assertRaises(IndexError): collection.pop(1000) self.assertEqual(collection.pop('model-1'), model1) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model2, model4]) with self.assertRaises(KeyError): collection.pop('model-1') self.assertEqual(collection.pop(model4), model4) self.assertEqual(len(collection), 1) self.assertListEqual(collection, [model2]) with self.assertRaises(KeyError): collection.pop(model4) def test_get(self): model1 = ExampleModel(id='model-1', field=False) model1b = ExampleModel(id='model-1', field=True) model2 = ExampleModel(id='model-2', field=False) collection = ExampleModel.collection([model1]) default = object() self.assertEqual(collection.get(0, default), model1) self.assertEqual(collection.get('model-1', default), model1) self.assertEqual(collection.get(model1, default), model1) self.assertEqual(collection.get(model1b, default), model1) self.assertIs(collection.get(1, default), default) self.assertIs(collection.get('model-2', default), default) self.assertIs(collection.get(model2, default), default) def test_clear(self): model1 = ExampleModel(id='model-1', field=False) model2 = ExampleModel(id='model-2', field=False) collection = ExampleModel.collection([model1, model2]) collection.clear() self.assertEqual(len(collection), 0) self.assertListEqual(collection, []) def test_validation(self): collection = ExampleModel.collection() with self.assertRaises(ValidationError): collection.append(ChildModel(id='model-1')) with self.assertRaises(ValidationError): collection.add(ChildModel(id='model-2')) def test_dump(self): collection = ExampleModel.collection([ ExampleModel(id='model-1', field=False), ExampleModel(id='model-2', field=True) ]) self.assertEqual(collection.dump(), [ { 'id': 'model-1', 'field': False, }, { 'id': 'model-2', 'field': True, }, ]) def test_dumps(self): collection = ExampleModel.collection([ ExampleModel(id='model-1', field=False), ExampleModel(id='model-3', field=False), ExampleModel(id='model-2', field=True) ]) # Object keys should be sorted, collection should maintain order self.assertEqual( collection.dumps(), '[\n' ' {\n' ' "field": false, \n' ' "id": "model-1"\n' ' }, \n' ' {\n' ' "field": false, \n' ' "id": "model-3"\n' ' }, \n' ' {\n' ' "field": true, \n' ' "id": "model-2"\n' ' }\n' ']') class PolymorphicCollectionTests(DataStoreTestCase): def test_create_(self): collection = PolymorphicChildBase.collection() self.assertEqual(len(collection), 0) self.assertListEqual(collection, []) def test_create_with_model(self): model = PolymorphicChildModel1(id='model-1', field1=False) collection = PolymorphicChildBase.collection([model]) self.assertEqual(len(collection), 1) self.assertListEqual(collection, [model]) def test_getitem(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) model2b = PolymorphicChildModel2(id='model-2', field2=True) model3 = PolymorphicChildModel1(id='model-3', field1=False) collection = PolymorphicChildBase.collection([model1, model2]) self.assertEqual(collection[0], model1) self.assertEqual(collection[1], model2) self.assertEqual(collection['model-1'], model1) self.assertEqual(collection['model-2'], model2) self.assertEqual(collection[model1], model1) self.assertEqual(collection[model1b], model1) self.assertEqual(collection[model2], model2) self.assertEqual(collection[model2b], model2) with self.assertRaises(IndexError): collection[2] with self.assertRaises(KeyError): collection['model-3'] with self.assertRaises(KeyError): collection[model3] def test_setitem_index(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) collection = PolymorphicChildBase.collection([model1]) collection[0] = model1b self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model1b) self.assertEqual(collection['model-1'], model1b) self.assertEqual(collection[model1], model1b) self.assertEqual(collection[model1b], model1b) collection[0] = model2 self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model2) self.assertEqual(collection['model-2'], model2) self.assertEqual(collection[model2], model2) with self.assertRaises(KeyError): collection['model-1'] with self.assertRaises(KeyError): collection[model1] with self.assertRaises(KeyError): collection[model1b] def test_setitem_key(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) collection = PolymorphicChildBase.collection([model1]) collection['model-1'] = model1b self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model1b) self.assertEqual(collection['model-1'], model1b) self.assertEqual(collection[model1], model1b) self.assertEqual(collection[model1b], model1b) collection['model-1'] = model2 self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model2) self.assertEqual(collection['model-2'], model2) self.assertEqual(collection[model2], model2) with self.assertRaises(KeyError): collection['model-1'] with self.assertRaises(KeyError): collection[model1] with self.assertRaises(KeyError): collection[model1b] def test_setitem_object(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) collection = PolymorphicChildBase.collection([model1]) collection[model1] = model1b self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model1b) self.assertEqual(collection['model-1'], model1b) self.assertEqual(collection[model1], model1b) self.assertEqual(collection[model1b], model1b) collection[model1] = model2 self.assertEqual(len(collection), 1) self.assertEqual(collection[0], model2) self.assertEqual(collection['model-2'], model2) self.assertEqual(collection[model2], model2) with self.assertRaises(KeyError): collection['model-1'] with self.assertRaises(KeyError): collection[model1] with self.assertRaises(KeyError): collection[model1b] def test_delitem_index(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model2 = PolymorphicChildModel2(id='model-2', field2=False) model3 = PolymorphicChildModel1(id='model-3', field1=False) collection = PolymorphicChildBase.collection([model1, model2, model3]) del collection[1] self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) def test_delitem_key(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model2 = PolymorphicChildModel2(id='model-2', field2=False) model3 = PolymorphicChildModel1(id='model-3', field1=False) collection = PolymorphicChildBase.collection([model1, model2, model3]) del collection['model-2'] self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) def test_delitem_object(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model2 = PolymorphicChildModel2(id='model-2', field2=False) model3 = PolymorphicChildModel1(id='model-3', field1=False) collection = PolymorphicChildBase.collection([model1, model2, model3]) del collection[model2] self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) def test_append(self): collection = PolymorphicChildBase.collection() model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) self.assertEqual(len(collection), 0) collection.append(model1) self.assertEqual(len(collection), 1) self.assertListEqual(collection, [model1]) collection.append(model2) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model2]) with self.assertRaises(ValueError): collection.append(model1b) def test_add(self): collection = PolymorphicChildBase.collection() model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) self.assertEqual(len(collection), 0) collection.add(model1) self.assertEqual(len(collection), 1) self.assertListEqual(collection, [model1]) collection.add(model2) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model2]) collection.add(model1b) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1b, model2]) def test_extend(self): collection = PolymorphicChildBase.collection() model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) self.assertEqual(len(collection), 0) collection.extend([model1, model2]) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model2]) with self.assertRaises(ValueError): collection.extend([model1b]) collection = PolymorphicChildBase.collection() with self.assertRaises(ValueError): collection.extend([model1, model2, model1b]) def test_update(self): collection = PolymorphicChildBase.collection() model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) self.assertEqual(len(collection), 0) collection.update([model1, model2]) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model2]) collection.update([model2, model1b]) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1b, model2]) def test_insert(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model2 = PolymorphicChildModel2(id='model-2', field2=False) model3 = PolymorphicChildModel1(id='model-3', field1=False) model4 = PolymorphicChildModel2(id='model-4', field2=False) model5 = PolymorphicChildModel1(id='model-5', field1=False) collection = PolymorphicChildBase.collection([model1, model2]) collection.insert(1, model3) self.assertEqual(len(collection), 3) self.assertListEqual(collection, [model1, model3, model2]) collection.insert(0, model4) self.assertEqual(len(collection), 4) self.assertListEqual(collection, [model4, model1, model3, model2]) with self.assertRaises(TypeError): collection.insert('model-2', model5) collection.insert(1000, model5) self.assertEqual(len(collection), 5) self.assertListEqual( collection, [model4, model1, model3, model2, model5]) # items in collection must be unique with self.assertRaises(ValueError): collection.insert(0, model2) def test_remove(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model2 = PolymorphicChildModel2(id='model-2', field2=False) model3 = PolymorphicChildModel1(id='model-3', field1=False) model4 = PolymorphicChildModel2(id='model-4', field2=False) collection = PolymorphicChildBase.collection([model1, model2, model3]) collection.remove(model2) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) with self.assertRaises(ValueError): collection.remove(model4) with self.assertRaises(ValidationError): collection.remove('model-2') def test_discard(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model2 = PolymorphicChildModel2(id='model-2', field2=False) model3 = PolymorphicChildModel1(id='model-3', field1=False) model4 = PolymorphicChildModel2(id='model-4', field2=False) collection = PolymorphicChildBase.collection([model1, model2, model3]) collection.discard(model2) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) collection.discard(model4) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model1, model3]) with self.assertRaises(ValidationError): collection.discard('model-2') def test_pop(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model2 = PolymorphicChildModel2(id='model-2', field2=False) model3 = PolymorphicChildModel1(id='model-3', field1=False) model4 = PolymorphicChildModel2(id='model-4', field2=False) model5 = PolymorphicChildModel1(id='model-5', field1=False) collection = PolymorphicChildBase.collection( [model1, model2, model3, model4, model5]) self.assertEqual(collection.pop(), model5) self.assertEqual(len(collection), 4) self.assertListEqual(collection, [model1, model2, model3, model4]) self.assertEqual(collection.pop(2), model3) self.assertEqual(len(collection), 3) self.assertListEqual(collection, [model1, model2, model4]) with self.assertRaises(IndexError): collection.pop(1000) self.assertEqual(collection.pop('model-1'), model1) self.assertEqual(len(collection), 2) self.assertListEqual(collection, [model2, model4]) with self.assertRaises(KeyError): collection.pop('model-1') self.assertEqual(collection.pop(model4), model4) self.assertEqual(len(collection), 1) self.assertListEqual(collection, [model2]) with self.assertRaises(KeyError): collection.pop(model4) def test_get(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model1b = PolymorphicChildModel1(id='model-1', field1=True) model2 = PolymorphicChildModel2(id='model-2', field2=False) collection = PolymorphicChildBase.collection([model1]) default = object() self.assertEqual(collection.get(0, default), model1) self.assertEqual(collection.get('model-1', default), model1) self.assertEqual(collection.get(model1, default), model1) self.assertEqual(collection.get(model1b, default), model1) self.assertIs(collection.get(1, default), default) self.assertIs(collection.get('model-2', default), default) self.assertIs(collection.get(model2, default), default) def test_clear(self): model1 = PolymorphicChildModel1(id='model-1', field1=False) model2 = PolymorphicChildModel2(id='model-2', field2=False) collection = PolymorphicChildBase.collection([model1, model2]) collection.clear() self.assertEqual(len(collection), 0) self.assertListEqual(collection, []) def test_validation(self): collection = PolymorphicChildBase.collection() with self.assertRaises(ValidationError): collection.append(ChildModel(id='model-1')) with self.assertRaises(ValidationError): collection.add(ChildModel(id='model-2')) def test_dump(self): collection = PolymorphicChildBase.collection([ PolymorphicChildModel1(id='model-1', field1=False), PolymorphicChildModel2(id='model-2', field2=True), ]) self.assertEqual(collection.dump(), [ { 'type': 'PolymorphicChildModel1', 'id': 'model-1', 'field1': False, 'parent': None, }, { '_type_': 'PolymorphicChildModel2', 'id': 'model-2', 'field2': True, 'parent': None, }, ]) def test_dumps(self): collection = PolymorphicChildBase.collection([ PolymorphicChildModel1(id='model-1', field1=False), PolymorphicChildModel2(id='model-3', field2=False), PolymorphicChildModel1(id='model-2', field1=True), ]) # Object keys should be sorted, collection should maintain order self.assertEqual( collection.dumps(), '[\n' ' {\n' ' "field1": false, \n' ' "id": "model-1", \n' ' "parent": null, \n' ' "type": "PolymorphicChildModel1"\n' ' }, \n' ' {\n' ' "_type_": "PolymorphicChildModel2", \n' ' "field2": false, \n' ' "id": "model-3", \n' ' "parent": null\n' ' }, \n' ' {\n' ' "field1": true, \n' ' "id": "model-2", \n' ' "parent": null, \n' ' "type": "PolymorphicChildModel1"\n' ' }\n' ']') ================================================ FILE: portia_server/portia_orm/tests/test_model.py ================================================ from unittest import mock from .utils import DataStoreTestCase, mock_storage from ..exceptions import ValidationError from ..models import ( Project, Schema, Field, Extractor, Spider, Sample, BaseAnnotation, Item, Annotation, SLYBOT_VERSION) class ProjectTestCase(DataStoreTestCase): def setUp(self): super(ProjectTestCase, self).setUp() self.storage = mock_storage(self.get_storage_files()) def get_storage_files(self): return { 'project.json': '{' ' "id": "example",' ' "name": "example"' '}', 'items.json': '{' ' "1664-4f20-b657": {' ' "auto_created": true,' ' "fields": {' ' "fbec-4a42-a4b0": {' ' "auto_created": true,' ' "id": "fbec-4a42-a4b0",' ' "name": "title",' ' "required": true,' ' "type": "text",' ' "vary": false' ' },' ' "cca5-490c-b604": {' ' "id": "cca5-490c-b604",' ' "name": "price",' ' "required": true,' ' "type": "price",' ' "vary": false' ' },' ' "34bc-406f-80bc": {' ' "id": "34bc-406f-80bc",' ' "name": "image",' ' "required": false,' ' "type": "image",' ' "vary": false' ' },' ' "ecfc-4dbe-b488": {' ' "id": "ecfc-4dbe-b488",' ' "name": "details",' ' "required": false,' ' "type": "text",' ' "vary": false' ' }' ' },' ' "name": "product"' ' },' ' "fa87-4791-8642": {' ' "fields": {},' ' "name": "other"' ' }' '}', 'extractors.json': '{' ' "e6fc-4758-9e6b": {' ' "id": "e6fc-4758-9e6b",' ' "regular_expression": "\\\\$(\\\\d+(?:\\\\.\\\\d{2}))"' ' },' ' "154f-45ce-bfbd": {' ' "id": "154f-45ce-bfbd",' ' "type_extractor": "number"' ' }' '}', 'spiders/shop-crawler.json': '{' ' "allowed_domains": [],' ' "exclude_patterns": [],' ' "follow_patterns": [],' ' "id": "shop-crawler",' ' "init_requests": [' ' {' ' "type": "login",' ' "loginurl": "http://shop.example.com/login",' ' "username": "user",' ' "password": "pass"' ' }' ' ],' ' "js_disable_patterns": [],' ' "js_enable_patterns": [],' ' "js_enabled": false,' ' "links_to_follow": "all",' ' "name": "shop-crawler",' ' "project": "example",' ' "respect_nofollow": true,' ' "start_urls": [\n' ' {\n' ' "type": "url", \n' ' "url": "http://example.com/"\n' ' }\n' ' ], \n' ' "template_names": [' ' "1ddc-4043-ac4d"' ' ]' '}', 'spiders/shop-crawler/1ddc-4043-ac4d.json': '{' ' "id": "1ddc-4043-ac4d",' ' "name": "example",' ' "url": "http://example.com",' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67",' ' "page_type": "item",' ' "spider": "shop-crawler",' ' "scrapes": "1664-4f20-b657",' ' "plugins": {' ' "annotations-plugin": {' ' "extracts": [' ' {' ' "id": "1e47-4833-a4d4",' ' "container_id": "1e47-4833-a4d4#parent",' ' "schema_id": "1664-4f20-b657",' ' "item_container": true,' ' "selector": ".main",' ' "repeated": true,' ' "siblings": 0,' ' "required": [],' ' "tagid": 18,' ' "text-content": "#portia-content",' ' "annotations": {' ' "#portia-content": "#dummy"' ' }' ' },' ' {' ' "id": "1e47-4833-a4d4#parent",' ' "container_id": null,' ' "schema_id": "1664-4f20-b657",' ' "item_container": true,' ' "selector": "body",' ' "repeated": false,' ' "siblings": 0,' ' "required": [],' ' "tagid": 18,' ' "text-content": "#portia-content",' ' "annotations": {' ' "#portia-content": "#dummy"' ' }' ' },' ' {' ' "id": "3606-4d68-a6a0",' ' "container_id": "1e47-4833-a4d4",' ' "selection_mode": "auto",' ' "selector": ".main > h1",' ' "accept_selectors": [' ' ".main:nth-child(1) > h1",' ' ".main:nth-child(2) > h1"' ' ],' ' "reject_selectors": [],' ' "data": {' ' "d1e2-4673-a72a": {' ' "field": "fbec-4a42-a4b0",' ' "attribute": "content",' ' "required": false,' ' "extractors": {}' ' }' ' },' ' "pre_text": null,' ' "post_text": null,' ' "tagid": null,' ' "required": []' ' },' ' {' ' "id": "5c18-40cf-8809",' ' "container_id": "1e47-4833-a4d4",' ' "selection_mode": "auto",' ' "selector": ".main > img",' ' "accept_selectors": [' ' ".main:nth-child(1) > img"' ' ],' ' "reject_selectors": [],' ' "data": {' ' "de35-49b5-b90b": {' ' "field": "34bc-406f-80bc",' ' "attribute": "content",' ' "required": false,' ' "extractors": [' ' "e6fc-4758-9e6b",' ' "154f-45ce-bfbd"' ' ]' ' }' ' },' ' "pre_text": null,' ' "post_text": null,' ' "tagid": null,' ' "required": []' ' }' ' ]' ' }' ' },' ' "version": "' + SLYBOT_VERSION + '"' '}', 'spiders/shop-crawler/1ddc-4043-ac4d/original_body.html': ( ''), 'spiders/shop-crawler/1ddc-4043-ac4d/rendered_body.html': ( ''), } class ProjectTests(ProjectTestCase): def test_project(self): project = Project(id='project-1') self.assertEqual(project.dump(), { 'id': 'project-1', }) def test_load(self): project = Project(self.storage, id='example', name='example') self.assertEqual(project.dump(), { 'id': 'example', 'name': 'example', }) self.storage.open.assert_not_called() def test_save(self): project = Project(self.storage, id='example') project.save() self.storage.open.assert_called_once_with('project.json') self.storage.save.assert_not_called() project.name = 'test' project.save() self.storage.open.assert_called_once_with('project.json') self.storage.save.assert_called_once_with('project.json', mock.ANY) self.assertEqual( self.storage.files['project.json'], '{\n' ' "id": "example", \n' ' "name": "test"\n' '}') def test_delete(self): project = Project(self.storage, id='example') project.delete() self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('items.json', mock.ANY), mock.call('extractors.json', mock.ANY)], any_order=True) self.assertEqual(self.storage.delete.call_count, 3) self.storage.delete.assert_has_calls([ mock.call('project.json'), mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) class SchemaTests(ProjectTestCase): def test_no_fields(self): schema = Schema(id='schema-1', name='default', auto_created=True) self.assertEqual(len(schema.fields), 0) self.assertEqual(schema.dump(), { 'schema-1': { 'name': 'default', 'fields': {}, 'auto_created': True, }, }) def test_fields(self): schema = Schema(id='schema-1', name='default') Field(id='field-1', name='name', schema=schema) Field(id='field-2', name='url', type='url', schema=schema) self.assertEqual(schema.dump(), { 'schema-1': { 'name': 'default', 'fields': { 'field-1': { 'id': 'field-1', 'name': 'name', 'type': 'text', 'required': False, 'vary': False, }, 'field-2': { 'id': 'field-2', 'name': 'url', 'type': 'url', 'required': False, 'vary': False, }, }, }, }) def test_collection(self): schemas = Schema.collection([ Schema(id='schema-1', name='default', fields=[ Field(id='field-1', name='name'), ]), Schema(id='schema-2', name='other', fields=[ Field(id='field-2', name='xxx'), ]), ]) self.assertEqual(schemas.dump(), { 'schema-1': { 'name': 'default', 'fields': { 'field-1': { 'id': 'field-1', 'name': 'name', 'type': 'text', 'required': False, 'vary': False, }, }, }, 'schema-2': { 'name': 'other', 'fields': { 'field-2': { 'id': 'field-2', 'name': 'xxx', 'type': 'text', 'required': False, 'vary': False, }, }, }, }) def test_load_through_project(self): project = Project(self.storage, id='example') schemas = project.schemas self.storage.open.assert_called_once_with('items.json') self.assertIsInstance(schemas, Schema.collection) self.assertEqual(schemas.dump(), { '1664-4f20-b657': { 'name': 'product', 'auto_created': True, 'fields': { 'fbec-4a42-a4b0': { 'auto_created': True, 'id': 'fbec-4a42-a4b0', 'name': 'title', 'type': 'text', 'required': True, 'vary': False, }, "cca5-490c-b604": { "id": "cca5-490c-b604", "name": "price", "required": True, "type": "price", "vary": False }, "34bc-406f-80bc": { "id": "34bc-406f-80bc", "name": "image", "required": False, "type": "image", "vary": False }, "ecfc-4dbe-b488": { "id": "ecfc-4dbe-b488", "name": "details", "required": False, "type": "text", "vary": False } }, }, 'fa87-4791-8642': { 'name': 'other', 'fields': {}, }, }) self.assertListEqual(list(schemas.keys()), ['1664-4f20-b657', 'fa87-4791-8642']) def test_load_through_partial(self): schema = Schema(self.storage, id='1664-4f20-b657') self.storage.open.assert_not_called() self.assertEqual(schema.dump(), { '1664-4f20-b657': { 'name': 'product', 'auto_created': True, 'fields': { 'fbec-4a42-a4b0': { 'auto_created': True, 'id': 'fbec-4a42-a4b0', 'name': 'title', 'type': 'text', 'required': True, 'vary': False, }, "cca5-490c-b604": { "id": "cca5-490c-b604", "name": "price", "required": True, "type": "price", "vary": False }, "34bc-406f-80bc": { "id": "34bc-406f-80bc", "name": "image", "required": False, "type": "image", "vary": False }, "ecfc-4dbe-b488": { "id": "ecfc-4dbe-b488", "name": "details", "required": False, "type": "text", "vary": False } }, }, }) self.storage.open.assert_called_once_with('items.json') def test_save_edit(self): schema = Project(self.storage, id='example').schemas['1664-4f20-b657'] schema.save() self.storage.open.assert_called_once_with('items.json') self.storage.save.assert_not_called() schema.name = 'test' schema.save() self.storage.open.assert_called_once_with('items.json') self.storage.save.assert_called_once_with('items.json', mock.ANY) self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "fbec-4a42-a4b0": {\n' ' "auto_created": true, \n' ' "id": "fbec-4a42-a4b0", \n' ' "name": "title", \n' ' "required": true, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "test"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') schema.id = 'xxxx-xxxx-xxxx' schema.save() self.storage.open.assert_called_once_with('items.json') self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('items.json', mock.ANY), mock.call('items.json', mock.ANY)]) self.assertEqual( self.storage.files['items.json'], '{\n' ' "xxxx-xxxx-xxxx": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "fbec-4a42-a4b0": {\n' ' "auto_created": true, \n' ' "id": "fbec-4a42-a4b0", \n' ' "name": "title", \n' ' "required": true, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "test"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') def test_save_new(self): project = Project(self.storage, id='example') schema = Schema(self.storage, id='xxxx-xxxx-xxxx', name='test1', project=project) schema.save() self.storage.open.assert_called_once_with('items.json') self.storage.save.assert_called_once_with('items.json', mock.ANY) self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "fbec-4a42-a4b0": {\n' ' "auto_created": true, \n' ' "id": "fbec-4a42-a4b0", \n' ' "name": "title", \n' ' "required": true, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }, \n' ' "xxxx-xxxx-xxxx": {\n' ' "fields": {}, \n' ' "name": "test1"\n' ' }\n' '}') project.schemas.insert( 0, Schema(self.storage, id='yyyy-yyyy-yyyy', name='test2')) project.schemas[0].save() self.storage.open.assert_called_once_with('items.json') self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('items.json', mock.ANY), mock.call('items.json', mock.ANY)]) self.assertEqual( self.storage.files['items.json'], '{\n' ' "yyyy-yyyy-yyyy": {\n' ' "fields": {}, \n' ' "name": "test2"\n' ' }, \n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "fbec-4a42-a4b0": {\n' ' "auto_created": true, \n' ' "id": "fbec-4a42-a4b0", \n' ' "name": "title", \n' ' "required": true, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }, \n' ' "xxxx-xxxx-xxxx": {\n' ' "fields": {}, \n' ' "name": "test1"\n' ' }\n' '}') def test_delete(self): project = Project(self.storage, id='example') schema = project.schemas['1664-4f20-b657'] schema.delete() self.storage.open.assert_called_once_with('items.json') self.storage.save.assert_called_once_with('items.json', mock.ANY) self.assertEqual( self.storage.files['items.json'], '{\n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') self.storage.delete.assert_not_called() self.assertListEqual(list(project.schemas.keys()), ['fa87-4791-8642']) class FieldTests(ProjectTestCase): def test_minimal_field(self): field = Field(id='field-1', name='url') self.assertEqual(field.dump(), { 'field-1': { 'id': 'field-1', 'name': 'url', 'type': 'text', 'required': False, 'vary': False, }, }) def test_full_field(self): field = Field(id='field-1', name='url', type='url', required=True, vary=True, auto_created=True) self.assertEqual(field.dump(), { 'field-1': { 'id': 'field-1', 'name': 'url', 'type': 'url', 'required': True, 'vary': True, 'auto_created': True, }, }) def test_field_types(self): field = Field(id='field-1', name='url') try: field.type = 'image' field.type = 'number' field.type = 'url' except ValidationError: self.fail( "Assigning to type attribute failed validation") with self.assertRaises(ValidationError): field.type = 'xxx' def test_load_through_project(self): project = Project(self.storage, id='example') fields = project.schemas['1664-4f20-b657'].fields self.storage.open.assert_called_once_with('items.json') self.assertIsInstance(fields, Field.collection) self.assertEqual(fields.dump(), { 'fbec-4a42-a4b0': { 'auto_created': True, 'id': 'fbec-4a42-a4b0', 'name': 'title', 'type': 'text', 'required': True, 'vary': False, }, "cca5-490c-b604": { "id": "cca5-490c-b604", "name": "price", "required": True, "type": "price", "vary": False }, "34bc-406f-80bc": { "id": "34bc-406f-80bc", "name": "image", "required": False, "type": "image", "vary": False }, "ecfc-4dbe-b488": { "id": "ecfc-4dbe-b488", "name": "details", "required": False, "type": "text", "vary": False }, }) self.assertListEqual(list(fields.keys()), ['fbec-4a42-a4b0', "cca5-490c-b604", "34bc-406f-80bc", "ecfc-4dbe-b488"]) def test_load_through_partial(self): field = Field(self.storage, id='ecfc-4dbe-b488') self.assertEqual(field.dump(), { "ecfc-4dbe-b488": { "id": "ecfc-4dbe-b488", "name": "details", "required": False, "type": "text", "vary": False }, }) self.storage.open.assert_called_once_with('items.json') def test_save_edit(self): schemas = Project(self.storage, id='example').schemas field = schemas['1664-4f20-b657'].fields['fbec-4a42-a4b0'] field.save() self.storage.open.assert_called_once_with('items.json') self.storage.save.assert_not_called() field.name = 'test' field.save() self.storage.open.assert_called_once_with('items.json') self.storage.save.assert_called_once_with('items.json', mock.ANY) self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "fbec-4a42-a4b0": {\n' ' "auto_created": true, \n' ' "id": "fbec-4a42-a4b0", \n' ' "name": "test", \n' ' "required": true, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') field.id = 'xxxx-xxxx-xxxx' field.save() self.storage.open.assert_called_once_with('items.json') self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('items.json', mock.ANY), mock.call('items.json', mock.ANY)]) self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "xxxx-xxxx-xxxx": {\n' ' "auto_created": true, \n' ' "id": "xxxx-xxxx-xxxx", \n' ' "name": "test", \n' ' "required": true, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') def test_save_new(self): schema = Project(self.storage, id='example').schemas['1664-4f20-b657'] field = Field(self.storage, id='xxxx-xxxx-xxxx', name='test1', schema=schema) field.save() self.storage.open.assert_called_once_with('items.json') self.storage.save.assert_called_once_with('items.json', mock.ANY) self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "fbec-4a42-a4b0": {\n' ' "auto_created": true, \n' ' "id": "fbec-4a42-a4b0", \n' ' "name": "title", \n' ' "required": true, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "xxxx-xxxx-xxxx": {\n' ' "id": "xxxx-xxxx-xxxx", \n' ' "name": "test1", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') schema.fields.insert( 0, Field(self.storage, id='yyyy-yyyy-yyyy', name='test2')) schema.fields[0].save() self.storage.open.assert_called_once_with('items.json') self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('items.json', mock.ANY), mock.call('items.json', mock.ANY)]) self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "yyyy-yyyy-yyyy": {\n' ' "id": "yyyy-yyyy-yyyy", \n' ' "name": "test2", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "fbec-4a42-a4b0": {\n' ' "auto_created": true, \n' ' "id": "fbec-4a42-a4b0", \n' ' "name": "title", \n' ' "required": true, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }, \n' ' "xxxx-xxxx-xxxx": {\n' ' "id": "xxxx-xxxx-xxxx", \n' ' "name": "test1", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') def test_delete(self): schema = Project(self.storage, id='example').schemas['1664-4f20-b657'] field = schema.fields['fbec-4a42-a4b0'] field.delete() self.storage.open.assert_called_once_with('items.json') self.storage.save.assert_called_once_with('items.json', mock.ANY) self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') self.storage.delete.assert_not_called() self.assertListEqual(list(schema.fields.keys()), ['cca5-490c-b604', '34bc-406f-80bc', 'ecfc-4dbe-b488']) class ExtractorTests(ProjectTestCase): def test_type_extractor(self): extractor = Extractor(id='extractor-1', type='type', value='url') self.assertEqual(extractor.dump(), { 'extractor-1': { 'id': 'extractor-1', 'type_extractor': 'url', }, }) try: extractor.value = 'image' extractor.value = 'number' extractor.value = 'text' except ValidationError: self.fail( "Assigning to value attribute failed validation") with self.assertRaises(ValidationError): extractor.value = 'xxx' def test_regexp_extractor(self): extractor = Extractor(id='extractor-1', type='regex', value='(.+)') self.assertEqual(extractor.dump(), { 'extractor-1': { 'id': 'extractor-1', 'regular_expression': '(.+)', }, }) try: extractor.value = '[xy]' except ValidationError: self.fail( "Assigning to value attribute failed validation") with self.assertRaises(ValidationError): extractor.value = '[xy' self.assertEqual(extractor.dump(), { 'extractor-1': { 'id': 'extractor-1', 'regular_expression': '[xy]', }, }) def test_extractor_type(self): extractor = Extractor(id='extractor-1', type='type', value='text') try: extractor.type = 'regex' extractor.type = 'type' except ValidationError: self.fail( "Assigning to type attribute failed validation") with self.assertRaises(ValidationError): extractor.type = 'xxx' def test_collection(self): extractors = Extractor.collection([ Extractor(id='extractor-1', type='type', value='url'), Extractor(id='extractor-2', type='regex', value='(.+)'), ]) self.assertEqual(extractors.dump(), { 'extractor-1': { 'id': 'extractor-1', 'type_extractor': 'url', }, 'extractor-2': { 'id': 'extractor-2', 'regular_expression': '(.+)', }, }) def test_load_through_project(self): project = Project(self.storage, id='example') extractors = project.extractors self.storage.open.assert_called_once_with('extractors.json') self.assertIsInstance(extractors, Extractor.collection) self.assertEqual(extractors.dump(), { "e6fc-4758-9e6b": { "id": "e6fc-4758-9e6b", "regular_expression": "\\$(\\d+(?:\\.\\d{2}))", }, "154f-45ce-bfbd": { "id": "154f-45ce-bfbd", "type_extractor": "number", }, }) self.assertListEqual(list(extractors.keys()), ['e6fc-4758-9e6b', "154f-45ce-bfbd"]) def test_load_through_partial(self): extractor = Extractor(self.storage, id='e6fc-4758-9e6b') self.assertEqual(extractor.dump(), { "e6fc-4758-9e6b": { "id": "e6fc-4758-9e6b", "regular_expression": "\\$(\\d+(?:\\.\\d{2}))", }, }) self.storage.open.assert_called_once_with('extractors.json') def test_save_edit(self): extractor = Project( self.storage, id='example').extractors['e6fc-4758-9e6b'] extractor.save() self.storage.open.assert_called_once_with('extractors.json') self.storage.save.assert_not_called() extractor.value = 'test' extractor.save() self.storage.open.assert_called_once_with('extractors.json') self.storage.save.assert_called_once_with('extractors.json', mock.ANY) self.assertEqual( self.storage.files['extractors.json'], '{\n' ' "e6fc-4758-9e6b": {\n' ' "id": "e6fc-4758-9e6b", \n' ' "regular_expression": "test"\n' ' }, \n' ' "154f-45ce-bfbd": {\n' ' "id": "154f-45ce-bfbd", \n' ' "type_extractor": "number"\n' ' }\n' '}') extractor.id = 'xxxx-xxxx-xxxx' extractor.save() self.storage.open.assert_called_once_with('extractors.json') self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('extractors.json', mock.ANY), mock.call('extractors.json', mock.ANY)]) self.assertEqual( self.storage.files['extractors.json'], '{\n' ' "xxxx-xxxx-xxxx": {\n' ' "id": "xxxx-xxxx-xxxx", \n' ' "regular_expression": "test"\n' ' }, \n' ' "154f-45ce-bfbd": {\n' ' "id": "154f-45ce-bfbd", \n' ' "type_extractor": "number"\n' ' }\n' '}') def test_save_new(self): project = Project(self.storage, id='example') extractor = Extractor(self.storage, id='xxxx-xxxx-xxxx', type='regex', value='test1', project=project) extractor.save() self.storage.open.assert_called_once_with('extractors.json') self.storage.save.assert_called_once_with('extractors.json', mock.ANY) self.assertEqual( self.storage.files['extractors.json'], '{\n' ' "e6fc-4758-9e6b": {\n' ' "id": "e6fc-4758-9e6b", \n' ' "regular_expression": "\\\\$(\\\\d+(?:\\\\.\\\\d{2}))"\n' ' }, \n' ' "154f-45ce-bfbd": {\n' ' "id": "154f-45ce-bfbd", \n' ' "type_extractor": "number"\n' ' }, \n' ' "xxxx-xxxx-xxxx": {\n' ' "id": "xxxx-xxxx-xxxx", \n' ' "regular_expression": "test1"\n' ' }\n' '}') project.extractors.insert( 0, Extractor(self.storage, id='yyyy-yyyy-yyyy', type='regex', value='test2')) project.extractors[0].save() self.storage.open.assert_called_once_with('extractors.json') self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('extractors.json', mock.ANY), mock.call('extractors.json', mock.ANY)]) self.assertEqual( self.storage.files['extractors.json'], '{\n' ' "yyyy-yyyy-yyyy": {\n' ' "id": "yyyy-yyyy-yyyy", \n' ' "regular_expression": "test2"\n' ' }, \n' ' "e6fc-4758-9e6b": {\n' ' "id": "e6fc-4758-9e6b", \n' ' "regular_expression": "\\\\$(\\\\d+(?:\\\\.\\\\d{2}))"\n' ' }, \n' ' "154f-45ce-bfbd": {\n' ' "id": "154f-45ce-bfbd", \n' ' "type_extractor": "number"\n' ' }, \n' ' "xxxx-xxxx-xxxx": {\n' ' "id": "xxxx-xxxx-xxxx", \n' ' "regular_expression": "test1"\n' ' }\n' '}') def test_delete(self): project = Project(self.storage, id='example') extractor = project.extractors['e6fc-4758-9e6b'] extractor.delete() self.storage.open.assert_called_once_with('extractors.json') self.storage.save.assert_called_once_with('extractors.json', mock.ANY) self.assertEqual( self.storage.files['extractors.json'], '{\n' ' "154f-45ce-bfbd": {\n' ' "id": "154f-45ce-bfbd", \n' ' "type_extractor": "number"\n' ' }\n' '}') self.storage.delete.assert_not_called() self.assertListEqual(list(project.extractors.keys()), ['154f-45ce-bfbd']) class SpiderTests(ProjectTestCase): def test_minimal_spider(self): spider = Spider(id='spider-1') spider.start_urls.append({'type': 'url', 'url': 'http://example.com'}) self.assertEqual(spider.dump(), { 'id': 'spider-1', 'start_urls': [{ 'type': 'url', 'url': 'http://example.com', }], 'links_to_follow': "all", 'allowed_domains': [], 'respect_nofollow': True, 'follow_patterns': [], 'exclude_patterns': [], 'js_enabled': False, 'js_enable_patterns': [], 'js_disable_patterns': [], }) def test_full_spider(self): spider = Spider( id='spider-1', start_urls=[{'type': 'url', 'url': 'http://example.com'}], links_to_follow="none", allowed_domains=['example.com'], respect_nofollow=False, follow_patterns=['.*'], exclude_patterns=['.*ignore.*'], js_enabled=True, js_enable_patterns=['.*'], js_disable_patterns=['.*ignore.*'], perform_login=True, login_url='http://shop.example.com/login', login_user='user', login_password='pass', samples=[ Sample(id='sample-1'), ], ) self.assertEqual(spider.dump(), { 'id': 'spider-1', 'start_urls': [{ 'type': 'url', 'url': 'http://example.com' }], 'links_to_follow': "none", 'allowed_domains': [ 'example.com', ], 'respect_nofollow': False, 'follow_patterns': [ '.*', ], 'exclude_patterns': [ '.*ignore.*', ], 'js_enabled': True, 'js_enable_patterns': [ '.*', ], 'js_disable_patterns': [ '.*ignore.*', ], 'init_requests': [ { 'type': 'login', 'loginurl': 'http://shop.example.com/login', 'username': 'user', 'password': 'pass' } ], }) def test_links_to_follow(self): spider = Spider(id='spider-1') try: spider.links_to_follow = 'patterns' spider.links_to_follow = 'auto' spider.links_to_follow = 'none' spider.links_to_follow = 'all' except ValidationError: self.fail( "Assigning to type attribute failed validation") with self.assertRaises(ValidationError): spider.links_to_follow = 'xxx' def test_load_through_project(self): project = Project(self.storage, id='example') spiders = project.spiders self.assertListEqual(list(spiders.keys()), ['shop-crawler']) self.assertIsInstance(spiders, Spider.collection) self.storage.open.assert_not_called() self.storage.listdir.assert_called_once_with('spiders') self.assertEqual(spiders.dump(), [ { "id": "shop-crawler", # "name": "shop-crawler", "start_urls": [{ "type": "url", "url": "http://example.com/" }], "links_to_follow": "all", "allowed_domains": [], "respect_nofollow": True, "follow_patterns": [], "exclude_patterns": [], "js_enabled": False, "js_enable_patterns": [], "js_disable_patterns": [], "init_requests": [ { "type": "login", "loginurl": "http://shop.example.com/login", "username": "user", "password": "pass" } ], }, ]) self.storage.open.assert_called_once_with('spiders/shop-crawler.json') def test_load_through_partial(self): spider = Spider(self.storage, id='shop-crawler') self.assertEqual(spider.dump(), { "id": "shop-crawler", # "name": "shop-crawler", "start_urls": [{ "type": "url", "url": "http://example.com/" }], "links_to_follow": "all", "allowed_domains": [], "respect_nofollow": True, "follow_patterns": [], "exclude_patterns": [], "js_enabled": False, "js_enable_patterns": [], "js_disable_patterns": [], "init_requests": [ { "type": "login", "loginurl": "http://shop.example.com/login", "username": "user", "password": "pass" } ], }) self.storage.open.assert_called_once_with('spiders/shop-crawler.json') def test_save_edit(self): spider = Project(self.storage, id='example').spiders['shop-crawler'] spider.save() self.storage.open.assert_called_once_with('spiders/shop-crawler.json') self.storage.save.assert_not_called() spider.follow_patterns.append('test') spider.save() self.storage.open.assert_called_once_with('spiders/shop-crawler.json') self.storage.save.assert_called_once_with( 'spiders/shop-crawler.json', mock.ANY) self.assertEqual( self.storage.files['spiders/shop-crawler.json'], '{\n' ' "allowed_domains": [], \n' ' "exclude_patterns": [], \n' ' "follow_patterns": [\n' ' "test"\n' ' ], \n' ' "id": "shop-crawler", \n' ' "init_requests": [\n' ' {\n' ' "type": "login", \n' ' "loginurl": "http://shop.example.com/login", \n' ' "username": "user", \n' ' "password": "pass"\n' ' }\n' ' ], \n' ' "js_disable_patterns": [], \n' ' "js_enable_patterns": [], \n' ' "js_enabled": false, \n' ' "links_to_follow": "all", \n' ' "respect_nofollow": true, \n' ' "start_urls": [\n' ' {\n' ' "type": "url", \n' ' "url": "http://example.com/"\n' ' }\n' ' ]\n' '}') spider.id = 'test-id' spider.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(self.storage.save.call_count, 3) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler.json', mock.ANY), mock.call('spiders/test-id.json', mock.ANY), mock.call('spiders/test-id/1ddc-4043-ac4d.json', mock.ANY)]) self.assertEqual(self.storage.delete.call_count, 2) self.storage.delete.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual( self.storage.files['spiders/test-id.json'], '{\n' ' "allowed_domains": [], \n' ' "exclude_patterns": [], \n' ' "follow_patterns": [\n' ' "test"\n' ' ], \n' ' "id": "test-id", \n' ' "init_requests": [\n' ' {\n' ' "type": "login", \n' ' "loginurl": "http://shop.example.com/login", \n' ' "username": "user", \n' ' "password": "pass"\n' ' }\n' ' ], \n' ' "js_disable_patterns": [], \n' ' "js_enable_patterns": [], \n' ' "js_enabled": false, \n' ' "links_to_follow": "all", \n' ' "respect_nofollow": true, \n' ' "start_urls": [\n' ' {\n' ' "type": "url", \n' ' "url": "http://example.com/"\n' ' }\n' ' ]\n' '}') def test_save_new(self): project = Project(self.storage, id='example') spider = Spider(self.storage, id='test1', project=project) spider.save() self.storage.open.assert_not_called() self.storage.save.assert_called_once_with( 'spiders/test1.json', mock.ANY) self.assertEqual( self.storage.files['spiders/test1.json'], '{\n' ' "allowed_domains": [], \n' ' "exclude_patterns": [], \n' ' "follow_patterns": [], \n' ' "id": "test1", \n' ' "js_disable_patterns": [], \n' ' "js_enable_patterns": [], \n' ' "js_enabled": false, \n' ' "links_to_follow": "all", \n' ' "respect_nofollow": true, \n' ' "start_urls": []\n' '}') project.spiders.insert(0, Spider(self.storage, id='test2')) project.spiders[0].save() self.storage.open.assert_not_called() self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('spiders/test1.json', mock.ANY), mock.call('spiders/test2.json', mock.ANY)]) self.assertEqual( self.storage.files['spiders/test2.json'], '{\n' ' "allowed_domains": [], \n' ' "exclude_patterns": [], \n' ' "follow_patterns": [], \n' ' "id": "test2", \n' ' "js_disable_patterns": [], \n' ' "js_enable_patterns": [], \n' ' "js_enabled": false, \n' ' "links_to_follow": "all", \n' ' "respect_nofollow": true, \n' ' "start_urls": []\n' '}') def test_delete(self): project = Project(self.storage, id='example') project.schemas # preload schemas spider = project.spiders['shop-crawler'] spider.delete() self.assertEqual(self.storage.open.call_count, 3) self.storage.open.assert_has_calls([ mock.call('items.json'), mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.storage.save.assert_called_once_with('items.json', mock.ANY) self.assertEqual(self.storage.delete.call_count, 2) self.storage.delete.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertListEqual(list(project.spiders.keys()), []) self.assertEqual( self.storage.files['items.json'], '{\n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') class SampleTests(ProjectTestCase): def test_minimal_sample(self): sample = Sample( id='sample-1', name='example', url='http://example.com') self.assertEqual(sample.dump(), { 'id': 'sample-1', 'name': 'example', 'url': 'http://example.com', 'page_id': '', 'page_type': 'item', 'spider': None, 'scrapes': None, 'plugins': { 'annotations-plugin': { 'extracts': [], }, }, 'extractors': {}, 'version': SLYBOT_VERSION, }) def test_full_sample(self): sample = Sample( id='sample-1', name='example', url='http://example.com', page_id='test-id', spider=Spider(id='spider-1')) self.assertEqual(sample.dump(), { 'id': 'sample-1', 'name': 'example', 'url': 'http://example.com', 'page_id': 'test-id', 'page_type': 'item', 'spider': 'spider-1', 'scrapes': None, 'plugins': { 'annotations-plugin': { 'extracts': [], }, }, 'extractors': {}, 'version': SLYBOT_VERSION, }) def test_load_through_project(self): project = Project(self.storage, id='example') samples = project.spiders['shop-crawler'].samples self.assertListEqual(list(samples.keys()), ['1ddc-4043-ac4d']) self.assertIsInstance(samples, Sample.collection) self.storage.open.assert_called_once_with('spiders/shop-crawler.json') self.assertEqual(samples.dump(), [ { 'id': '1ddc-4043-ac4d', 'name': 'example', 'url': 'http://example.com', 'page_id': 'ab5bbf650b32ca41af6f8e9976fc3c85eee87f67', 'page_type': 'item', 'spider': 'shop-crawler', 'scrapes': '1664-4f20-b657', 'plugins': { 'annotations-plugin': { 'extracts': [ { 'annotations': { '#portia-content': '#dummy', }, 'container_id': None, 'id': '1e47-4833-a4d4#parent', 'item_container': True, 'repeated': False, 'required': [], 'schema_id': '1664-4f20-b657', 'selector': 'body', 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }, { 'annotations': { '#portia-content': '#dummy', }, 'container_id': '1e47-4833-a4d4#parent', 'id': '1e47-4833-a4d4', 'item_container': True, 'repeated': True, 'required': [], 'schema_id': '1664-4f20-b657', 'selector': '.main', 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }, { 'accept_selectors': [ '.main:nth-child(1) > h1', '.main:nth-child(2) > h1', ], 'container_id': '1e47-4833-a4d4', 'data': { 'd1e2-4673-a72a': { 'attribute': 'content', 'extractors': {}, 'field': 'fbec-4a42-a4b0', 'required': False, }, }, 'id': '3606-4d68-a6a0', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'repeated': False, 'required': [], 'selection_mode': 'auto', 'selector': '.main > h1', 'tagid': None, 'xpath': None, }, { 'accept_selectors': [ '.main:nth-child(1) > img', ], 'container_id': '1e47-4833-a4d4', 'data': { 'de35-49b5-b90b': { 'attribute': 'content', 'extractors': [ 'e6fc-4758-9e6b', '154f-45ce-bfbd', ], 'field': '34bc-406f-80bc', 'required': False, }, }, 'id': '5c18-40cf-8809', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'repeated': False, 'required': [], 'selection_mode': 'auto', 'selector': '.main > img', 'tagid': None, 'xpath': None, }, ], }, }, 'extractors': {}, 'version': SLYBOT_VERSION, }, ]) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) def test_load_through_partial(self): sample = Sample(self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler')) self.assertEqual(sample.dump(), { 'id': '1ddc-4043-ac4d', 'name': 'example', 'url': 'http://example.com', 'page_id': 'ab5bbf650b32ca41af6f8e9976fc3c85eee87f67', 'page_type': 'item', 'spider': 'shop-crawler', 'scrapes': '1664-4f20-b657', 'plugins': { 'annotations-plugin': { 'extracts': [ { 'annotations': { '#portia-content': '#dummy', }, 'container_id': None, 'id': '1e47-4833-a4d4#parent', 'item_container': True, 'repeated': False, 'required': [], 'schema_id': '1664-4f20-b657', 'selector': 'body', 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }, { 'annotations': { '#portia-content': '#dummy', }, 'container_id': '1e47-4833-a4d4#parent', 'id': '1e47-4833-a4d4', 'item_container': True, 'repeated': True, 'required': [], 'schema_id': '1664-4f20-b657', 'selector': '.main', 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }, { 'accept_selectors': [ '.main:nth-child(1) > h1', '.main:nth-child(2) > h1', ], 'container_id': '1e47-4833-a4d4', 'data': { 'd1e2-4673-a72a': { 'attribute': 'content', 'extractors': {}, 'field': 'fbec-4a42-a4b0', 'required': False, }, }, 'id': '3606-4d68-a6a0', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'required': [], 'repeated': False, 'selection_mode': 'auto', 'selector': '.main > h1', 'tagid': None, 'xpath': None, }, { 'accept_selectors': [ '.main:nth-child(1) > img', ], 'container_id': '1e47-4833-a4d4', 'data': { 'de35-49b5-b90b': { 'attribute': 'content', 'extractors': [ 'e6fc-4758-9e6b', '154f-45ce-bfbd', ], 'field': '34bc-406f-80bc', 'required': False, }, }, 'id': '5c18-40cf-8809', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'required': [], 'repeated': False, 'selection_mode': 'auto', 'selector': '.main > img', 'tagid': None, 'xpath': None, }, ], }, }, 'extractors': {}, 'version': SLYBOT_VERSION, }) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) def test_save_edit(self): sample = Sample(self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler')) sample.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.storage.save.assert_not_called() sample.original_body.html = '' sample.original_body.save() self.storage.save.assert_called_once_with( 'spiders/shop-crawler/1ddc-4043-ac4d/original_body.html', mock.ANY) sample.page_id = sample.id sample.save() self.assertEqual(self.storage.open.call_count, 3) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "1ddc-4043-ac4d", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > h1", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') sample.id = 'test-id' sample.save() self.assertEqual(self.storage.open.call_count, 3) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(self.storage.save.call_count, 5) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/1ddc-4043-ac4d/original_body.html', mock.ANY), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY), mock.call('spiders/shop-crawler/test-id.json', mock.ANY), mock.call('spiders/shop-crawler/test-id/original_body.html', mock.ANY), mock.call('spiders/shop-crawler.json', mock.ANY), ]) self.assertEqual( self.storage.files['spiders/shop-crawler/test-id.json'], '{\n' ' "extractors": {}, \n' ' "id": "test-id", \n' ' "name": "example", \n' ' "page_id": "1ddc-4043-ac4d", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > h1", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') self.assertEqual( self.storage.files['spiders/shop-crawler.json'], '{\n' ' "allowed_domains": [], \n' ' "exclude_patterns": [], \n' ' "follow_patterns": [], \n' ' "id": "shop-crawler", \n' ' "init_requests": [\n' ' {\n' ' "type": "login", \n' ' "loginurl": "http://shop.example.com/login", \n' ' "username": "user", \n' ' "password": "pass"\n' ' }\n' ' ], \n' ' "js_disable_patterns": [], \n' ' "js_enable_patterns": [], \n' ' "js_enabled": false, \n' ' "links_to_follow": "all", \n' ' "respect_nofollow": true, \n' ' "start_urls": [\n' ' {\n' ' "type": "url", \n' ' "url": "http://example.com/"\n' ' }\n' ' ]\n' '}') def test_save_new(self): spider = Spider(self.storage, id='shop-crawler', project=Project(self.storage, id='example')) sample = Sample(self.storage, id='test1', name='test sample 1', url='http://example.com/test1', spider=spider) sample.save() self.storage.open.assert_called_once_with('spiders/shop-crawler.json') self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/test1.json', mock.ANY), mock.call('spiders/shop-crawler.json', mock.ANY)]) self.assertEqual( self.storage.files['spiders/shop-crawler/test1.json'], '{\n' ' "extractors": {}, \n' ' "id": "test1", \n' ' "name": "test sample 1", \n' ' "page_id": "", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": []\n' ' }\n' ' }, \n' ' "scrapes": null, \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com/test1", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') spider.samples.insert(0, Sample(self.storage, id='test2', name='test sample 2', url='http://example.com/test2')) spider.samples[0].save() self.storage.open.assert_called_once_with('spiders/shop-crawler.json') self.assertEqual(self.storage.save.call_count, 4) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/test1.json', mock.ANY), mock.call('spiders/shop-crawler.json', mock.ANY), mock.call('spiders/shop-crawler/test2.json', mock.ANY), mock.call('spiders/shop-crawler.json', mock.ANY)]) self.assertEqual( self.storage.files['spiders/shop-crawler/test2.json'], '{\n' ' "extractors": {}, \n' ' "id": "test2", \n' ' "name": "test sample 2", \n' ' "page_id": "", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": []\n' ' }\n' ' }, \n' ' "scrapes": null, \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com/test2", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') def test_delete(self): project = Project(self.storage, id='example') project.schemas # preload schemas spider = Spider(self.storage, id='shop-crawler', project=project) sample = spider.samples['1ddc-4043-ac4d'] sample.delete() self.assertEqual(self.storage.open.call_count, 5) self.storage.open.assert_has_calls([ mock.call('items.json'), mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json'), mock.call( 'spiders/shop-crawler/1ddc-4043-ac4d/rendered_body.html'), mock.call( 'spiders/shop-crawler/1ddc-4043-ac4d/original_body.html'), ]) self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('items.json', mock.ANY), mock.call('spiders/shop-crawler.json', mock.ANY)]) self.assertEqual(self.storage.delete.call_count, 3) self.storage.delete.assert_has_calls([ mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d/rendered_body.html'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d/original_body.html') ]) self.assertListEqual(list(spider.samples.keys()), []) self.assertEqual( self.storage.files['spiders/shop-crawler.json'], '{\n' ' "allowed_domains": [], \n' ' "exclude_patterns": [], \n' ' "follow_patterns": [], \n' ' "id": "shop-crawler", \n' ' "init_requests": [\n' ' {\n' ' "type": "login", \n' ' "loginurl": "http://shop.example.com/login", \n' ' "username": "user", \n' ' "password": "pass"\n' ' }\n' ' ], \n' ' "js_disable_patterns": [], \n' ' "js_enable_patterns": [], \n' ' "js_enabled": false, \n' ' "links_to_follow": "all", \n' ' "respect_nofollow": true, \n' ' "start_urls": [\n' ' {\n' ' "type": "url", \n' ' "url": "http://example.com/"\n' ' }\n' ' ]\n' '}') self.assertEqual( self.storage.files['items.json'], '{\n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') class ItemTests(ProjectTestCase): def get_storage_files(self): return dict(super(ItemTests, self).get_storage_files(), **{ 'items.json': '{' ' "1664-4f20-b657": {' ' "fields": {' ' "fbec-4a42-a4b0": {' ' "auto_created": true,' ' "id": "fbec-4a42-a4b0",' ' "name": "title",' ' "required": true,' ' "type": "text",' ' "vary": false' ' },' ' "cca5-490c-b604": {' ' "id": "cca5-490c-b604",' ' "name": "price",' ' "required": true,' ' "type": "price",' ' "vary": false' ' },' ' "34bc-406f-80bc": {' ' "id": "34bc-406f-80bc",' ' "name": "image",' ' "required": false,' ' "type": "image",' ' "vary": false' ' },' ' "ecfc-4dbe-b488": {' ' "id": "ecfc-4dbe-b488",' ' "name": "details",' ' "required": false,' ' "type": "text",' ' "vary": false' ' }' ' },' ' "name": "product"' ' },' ' "fa87-4791-8642": {' ' "fields": {},' ' "name": "other"' ' }' '}', 'spiders/shop-crawler/1ddc-4043-ac4d.json': '{' ' "id": "1ddc-4043-ac4d",' ' "name": "example",' ' "url": "http://example.com",' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67",' ' "page_type": "item",' ' "spider": "shop-crawler",' ' "scrapes": "1664-4f20-b657",' ' "plugins": {' ' "annotations-plugin": {' ' "extracts": [' ' {' ' "id": "1e47-4833-a4d4",' ' "container_id": "1e47-4833-a4d4#parent",' ' "schema_id": "1664-4f20-b657",' ' "item_container": true,' ' "selector": ".main",' ' "repeated": true,' ' "siblings": 0,' ' "required": [],' ' "tagid": 18,' ' "text-content": "#portia-content",' ' "annotations": {' ' "#portia-content": "#dummy"' ' }' ' },' ' {' ' "id": "1e47-4833-a4d4#parent",' ' "container_id": null,' ' "schema_id": "1664-4f20-b657",' ' "item_container": true,' ' "selector": "body",' ' "repeated": false,' ' "siblings": 0,' ' "required": [],' ' "tagid": 18,' ' "text-content": "#portia-content",' ' "annotations": {' ' "#portia-content": "#dummy"' ' }' ' },' ' {' ' "id": "3606-4d68-a6a0",' ' "container_id": "1e47-4833-a4d4",' ' "selection_mode": "auto",' ' "selector": ".main > h1",' ' "accept_selectors": [' ' ".main:nth-child(1) > h1",' ' ".main:nth-child(2) > h1"' ' ],' ' "reject_selectors": [],' ' "data": {' ' "d1e2-4673-a72a": {' ' "field": "fbec-4a42-a4b0",' ' "attribute": "content",' ' "required": false,' ' "extractors": {}' ' }' ' },' ' "pre_text": null,' ' "post_text": null,' ' "tagid": null,' ' "required": []' ' },' ' {' ' "id": "b161-47b1-b064",' ' "container_id": "1e47-4833-a4d4",' ' "schema_id": "1664-4f20-b657",' ' "item_container": true,' ' "selector": ".main > div",' ' "repeated": false,' ' "siblings": 0,' ' "required": [],' ' "tagid": 18,' ' "text-content": "#portia-content",' ' "annotations": {' ' "#portia-content": "#dummy"' ' }' ' },' ' {' ' "id": "5c18-40cf-8809",' ' "container_id": "1e47-4833-a4d4",' ' "selection_mode": "auto",' ' "selector": ".main > img",' ' "accept_selectors": [' ' ".main:nth-child(1) > img"' ' ],' ' "reject_selectors": [],' ' "data": {' ' "de35-49b5-b90b": {' ' "field": "34bc-406f-80bc",' ' "attribute": "content",' ' "required": false,' ' "extractors": [' ' "e6fc-4758-9e6b",' ' "154f-45ce-bfbd"' ' ]' ' }' ' },' ' "pre_text": null,' ' "post_text": null,' ' "tagid": null,' ' "required": []' ' },' ' {' ' "id": "7fd9-4ba9-83b8",' ' "container_id": "b161-47b1-b064",' ' "selection_mode": "auto",' ' "selector": ".main > div > span",' ' "accept_selectors": [' ' ".main:nth-child(1) > div > span"' ' ],' ' "reject_selectors": [],' ' "data": {' ' "6535-4215-b774": {' ' "field": "cca5-490c-b604",' ' "attribute": "content",' ' "required": false,' ' "extractors": {}' ' }' ' },' ' "pre_text": null,' ' "post_text": null,' ' "tagid": null,' ' "required": []' ' }' ' ]' ' }' ' },' ' "version": "' + SLYBOT_VERSION + '"' '}', 'spiders/shop-crawler/1ddc-4043-ac4d/original_body.html': ( '') }) def test_minimal_item(self): item = Item(id='item-1') self.assertEqual(item.dump(), { 'annotations': { '#portia-content': '#dummy', }, 'children': [], 'container_id': None, 'id': 'item-1', 'item_container': True, 'repeated': False, 'repeated_selector': None, 'required': [], 'schema_id': None, 'selector': None, 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }) def test_full_item(self): item = Item( id='item-1', name='test', selector='body', repeated_selector='.item', siblings=2, schema=Schema(id='schema-1'), annotations=[]) self.assertEqual(item.dump(), { 'annotations': { '#portia-content': '#dummy', }, 'children': [], 'container_id': None, 'field': 'test', 'id': 'item-1', 'item_container': True, 'repeated': True, 'repeated_selector': '.item', 'required': [], 'schema_id': 'schema-1', 'selector': 'body', 'siblings': 2, 'tagid': None, 'text-content': '#portia-content', }) def test_with_annotation(self): item = Item(id='item-1') item.annotations.append(Annotation(id='annotation-1|data-1')) self.assertEqual(item.dump(), { 'annotations': { '#portia-content': '#dummy', }, 'children': [ { "accept_selectors": [], "container_id": "item-1", "data": { "data-1": { "attribute": "content", "extractors": {}, "field": None, "required": False, }, }, "id": "annotation-1", 'text-content': 'content', "post_text": None, "pre_text": None, "reject_selectors": [], "repeated": False, "required": [], "selection_mode": "auto", "selector": None, "tagid": None, "xpath": None, }, ], 'container_id': None, 'id': 'item-1', 'item_container': True, 'repeated': False, 'repeated_selector': None, 'required': [], 'schema_id': None, 'selector': None, 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }) def test_with_nested_item(self): item = Item(id='item-1') item.annotations.append(Item(id='item-2')) self.assertEqual(item.dump(), { 'annotations': { '#portia-content': '#dummy', }, 'children': [ { "annotations": { "#portia-content": "#dummy", }, "children": [], "container_id": "item-1", "id": "item-2", "item_container": True, "repeated": False, "repeated_selector": None, "required": [], "schema_id": None, "selector": None, "siblings": 0, "tagid": None, "text-content": "#portia-content", }, ], 'container_id': None, 'id': 'item-1', 'item_container': True, 'repeated': False, 'repeated_selector': None, 'required': [], 'schema_id': None, 'selector': None, 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }) def test_load_through_project(self): project = Project(self.storage, id='example') items = project.spiders['shop-crawler'].samples['1ddc-4043-ac4d'].items self.assertListEqual(list(items.keys()), ['1e47-4833-a4d4']) self.assertIsInstance(items, Item.collection) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(items.dump(), [ { 'annotations': { '#portia-content': '#dummy', }, 'children': [ { 'accept_selectors': [ '.main:nth-child(1) > h1', '.main:nth-child(2) > h1', ], 'container_id': '1e47-4833-a4d4', 'data': { 'd1e2-4673-a72a': { 'attribute': 'content', 'extractors': {}, 'field': 'fbec-4a42-a4b0', 'required': False, }, }, 'id': '3606-4d68-a6a0', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'required': [], 'repeated': False, 'selection_mode': 'auto', 'selector': '.main > h1', 'tagid': None, 'xpath': None, }, { 'annotations': { '#portia-content': '#dummy', }, 'children': [ { 'accept_selectors': [ '.main:nth-child(1) > div > span', ], 'container_id': 'b161-47b1-b064', 'data': { '6535-4215-b774': { 'attribute': 'content', 'extractors': {}, 'field': 'cca5-490c-b604', 'required': False, }, }, 'id': '7fd9-4ba9-83b8', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'repeated': False, 'required': [], 'selection_mode': 'auto', 'selector': '.main > div > span', 'tagid': None, 'xpath': None, }, ], 'container_id': '1e47-4833-a4d4', 'id': 'b161-47b1-b064', 'item_container': True, 'repeated': False, 'repeated_selector': None, 'required': [], 'schema_id': '1664-4f20-b657', 'selector': '.main > div', 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }, { 'accept_selectors': [ '.main:nth-child(1) > img', ], 'container_id': '1e47-4833-a4d4', 'data': { 'de35-49b5-b90b': { 'attribute': 'content', 'extractors': [ 'e6fc-4758-9e6b', '154f-45ce-bfbd', ], 'field': '34bc-406f-80bc', 'required': False, }, }, 'id': '5c18-40cf-8809', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'required': [], 'repeated': False, 'selection_mode': 'auto', 'selector': '.main > img', 'tagid': None, 'xpath': None, }, ], 'container_id': None, 'id': '1e47-4833-a4d4', 'item_container': True, 'repeated': True, 'repeated_selector': '.main', 'required': [], 'schema_id': '1664-4f20-b657', 'selector': 'body', 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }, ]) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) def test_load_through_partial(self): item = Item( self.storage, id='1e47-4833-a4d4', sample=Sample( self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler'))) self.assertEqual(item.dump(), { 'annotations': { '#portia-content': '#dummy', }, 'children': [ { 'accept_selectors': [ '.main:nth-child(1) > h1', '.main:nth-child(2) > h1', ], 'container_id': '1e47-4833-a4d4', 'data': { 'd1e2-4673-a72a': { 'attribute': 'content', 'extractors': {}, 'field': 'fbec-4a42-a4b0', 'required': False, }, }, 'id': '3606-4d68-a6a0', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'required': [], 'repeated': False, 'selection_mode': 'auto', 'selector': '.main > h1', 'tagid': None, 'xpath': None, }, { 'annotations': { '#portia-content': '#dummy', }, 'children': [ { 'accept_selectors': [ '.main:nth-child(1) > div > span', ], 'container_id': 'b161-47b1-b064', 'data': { '6535-4215-b774': { 'attribute': 'content', 'extractors': {}, 'field': 'cca5-490c-b604', 'required': False, }, }, 'id': '7fd9-4ba9-83b8', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'repeated': False, 'required': [], 'selection_mode': 'auto', 'selector': '.main > div > span', 'tagid': None, 'xpath': None, }, ], 'container_id': '1e47-4833-a4d4', 'id': 'b161-47b1-b064', 'item_container': True, 'repeated': False, 'repeated_selector': None, 'required': [], 'schema_id': '1664-4f20-b657', 'selector': '.main > div', 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }, { 'accept_selectors': [ '.main:nth-child(1) > img', ], 'container_id': '1e47-4833-a4d4', 'data': { 'de35-49b5-b90b': { 'attribute': 'content', 'extractors': [ 'e6fc-4758-9e6b', '154f-45ce-bfbd', ], 'field': '34bc-406f-80bc', 'required': False, }, }, 'id': '5c18-40cf-8809', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'required': [], 'repeated': False, 'selection_mode': 'auto', 'selector': '.main > img', 'tagid': None, 'xpath': None, }, ], 'container_id': None, 'id': '1e47-4833-a4d4', 'item_container': True, 'repeated': True, 'repeated_selector': '.main', 'required': [], 'schema_id': '1664-4f20-b657', 'selector': 'body', 'siblings': 0, 'tagid': None, 'text-content': '#portia-content', }) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) def test_save_edit(self): item = Item( self.storage, id='1e47-4833-a4d4', sample=Sample( self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler'))) item.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.storage.save.assert_not_called() item.selector = '#test' item.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.storage.save.assert_called_once_with( 'spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "#test", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > h1", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4", \n' ' "id": "b161-47b1-b064", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main > div", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > div > span"\n' ' ], \n' ' "container_id": "b161-47b1-b064", \n' ' "data": {\n' ' "6535-4215-b774": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "cca5-490c-b604", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "7fd9-4ba9-83b8", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > div > span", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') item.id = 'test-id' item.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY)]) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "test-id#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "#test", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "test-id#parent", \n' ' "id": "test-id", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "test-id", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > h1", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "test-id", \n' ' "id": "b161-47b1-b064", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main > div", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > div > span"\n' ' ], \n' ' "container_id": "b161-47b1-b064", \n' ' "data": {\n' ' "6535-4215-b774": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "cca5-490c-b604", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "7fd9-4ba9-83b8", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > div > span", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "test-id", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') def test_save_new(self): sample = Sample(self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler', project=Project(self.storage, id='example'))) item = Item(self.storage, id='test1', sample=sample) item.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.storage.save.assert_called_once_with( 'spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > h1", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4", \n' ' "id": "b161-47b1-b064", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main > div", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > div > span"\n' ' ], \n' ' "container_id": "b161-47b1-b064", \n' ' "data": {\n' ' "6535-4215-b774": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "cca5-490c-b604", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "7fd9-4ba9-83b8", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > div > span", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "test1", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": null, \n' ' "selector": null, \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') sample.items.insert(0, Item(self.storage, id='test2', selector='#xxx', repeated_selector='.yyy')) sample.items[0].save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY)]) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "test2#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": null, \n' ' "selector": "#xxx", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "test2#parent", \n' ' "id": "test2", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": null, \n' ' "selector": ".yyy", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > h1", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4", \n' ' "id": "b161-47b1-b064", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main > div", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > div > span"\n' ' ], \n' ' "container_id": "b161-47b1-b064", \n' ' "data": {\n' ' "6535-4215-b774": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "cca5-490c-b604", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "7fd9-4ba9-83b8", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > div > span", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "test1", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": null, \n' ' "selector": null, \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') def test_delete(self): project = Project(self.storage, id='example') project.schemas # preload schemas sample = Sample(self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler', project=project)) item = sample.items['1e47-4833-a4d4'] item.delete() self.assertEqual(self.storage.open.call_count, 3) self.storage.open.assert_has_calls([ mock.call('items.json'), mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY), mock.call('items.json', mock.ANY)]) self.storage.delete.assert_not_called() self.assertListEqual(list(sample.items.keys()), []) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": []\n' ' }\n' ' }, \n' ' "scrapes": null, \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "fields": {\n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') class AnnotationTests(ProjectTestCase): def test_minimal_item(self): annotation = Annotation(id='annotation-1|data-1') self.assertEqual(annotation.dump(), { 'accept_selectors': [], 'container_id': None, 'data': { 'data-1': { 'attribute': 'content', 'extractors': {}, 'field': None, 'required': False, }, }, 'id': 'annotation-1', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'repeated': False, 'required': [], 'selection_mode': 'auto', 'selector': None, 'tagid': None, 'xpath': None, }) def test_full_item(self): annotation = Annotation( id='annotation-1|data-1', attribute='src', required=True, selection_mode='css', selector='img', accept_selectors=['img'], reject_selectors=['video'], pre_text='pre ', post_text=' post', parent=Item(id='item-1'), field=Field(id='field-1')) self.assertEqual(annotation.dump(), { 'accept_selectors': [ 'img', ], 'container_id': 'item-1', 'data': { 'data-1': { 'attribute': 'src', 'extractors': {}, 'field': 'field-1', 'required': True, }, }, 'id': 'annotation-1', 'text-content': 'content', 'post_text': ' post', 'pre_text': 'pre ', 'reject_selectors': [ 'video', ], 'repeated': False, 'required': [], 'selection_mode': 'css', 'selector': 'img', 'tagid': None, 'xpath': None, }) def test_load_through_project(self): project = Project(self.storage, id='example') annotations = (project.spiders['shop-crawler'].samples['1ddc-4043-ac4d'] .items['1e47-4833-a4d4'].annotations) self.assertListEqual(list(annotations.keys()), ['3606-4d68-a6a0|d1e2-4673-a72a', '5c18-40cf-8809|de35-49b5-b90b']) self.assertIsInstance(annotations, BaseAnnotation.collection) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(annotations.dump(), [ { 'accept_selectors': [ '.main:nth-child(1) > h1', '.main:nth-child(2) > h1', ], 'container_id': '1e47-4833-a4d4', 'data': { 'd1e2-4673-a72a': { 'attribute': 'content', 'extractors': {}, 'field': 'fbec-4a42-a4b0', 'required': False, }, }, 'id': '3606-4d68-a6a0', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'repeated': False, 'required': [], 'selection_mode': 'auto', 'selector': '.main > h1', 'tagid': None, 'xpath': None, }, { 'accept_selectors': [ '.main:nth-child(1) > img', ], 'container_id': '1e47-4833-a4d4', 'data': { 'de35-49b5-b90b': { 'attribute': 'content', 'extractors': [ 'e6fc-4758-9e6b', '154f-45ce-bfbd', ], 'field': '34bc-406f-80bc', 'required': False, }, }, 'id': '5c18-40cf-8809', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'repeated': False, 'required': [], 'selection_mode': 'auto', 'selector': '.main > img', 'tagid': None, 'xpath': None, }, ]) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) def test_load_through_partial(self): annotation = Annotation( self.storage, id='5c18-40cf-8809|de35-49b5-b90b', parent=Item( self.storage, id='1e47-4833-a4d4', sample=Sample( self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler')))) self.assertEqual(annotation.dump(), { 'accept_selectors': [ '.main:nth-child(1) > img', ], 'container_id': '1e47-4833-a4d4', 'data': { 'de35-49b5-b90b': { 'attribute': 'content', 'extractors': [ 'e6fc-4758-9e6b', '154f-45ce-bfbd', ], 'field': '34bc-406f-80bc', 'required': False, }, }, 'id': '5c18-40cf-8809', 'text-content': 'content', 'post_text': None, 'pre_text': None, 'reject_selectors': [], 'repeated': False, 'required': [], 'selection_mode': 'auto', 'selector': '.main > img', 'tagid': None, 'xpath': None, }) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) def test_save_edit(self): annotation = Annotation( self.storage, id='3606-4d68-a6a0|d1e2-4673-a72a', parent=Item( self.storage, id='1e47-4833-a4d4', sample=Sample( self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler')))) annotation.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.storage.save.assert_not_called() annotation.selector = '.test' annotation.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.storage.save.assert_called_once_with( 'spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".test", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') annotation.id = 'test-id|data-id' annotation.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY)]) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "data-id": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "test-id", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".test", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') def test_save_new(self): item = Item( self.storage, id='1e47-4833-a4d4', sample=Sample( self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler'))) annotation = Annotation(self.storage, id='test1|data1', parent=item) annotation.save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.storage.save.assert_called_once_with( 'spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > h1", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "data1": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": null, \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "test1", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": null, \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') item.annotations.insert(0, Annotation(self.storage, id='test2|data2')) item.annotations[0].save() self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY)]) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "data2": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": null, \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "test2", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": null, \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > h1", \n' ' ".main:nth-child(2) > h1"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "d1e2-4673-a72a": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": "fbec-4a42-a4b0", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "3606-4d68-a6a0", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > h1", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }, \n' ' {\n' ' "accept_selectors": [], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "data1": {\n' ' "attribute": "content", \n' ' "extractors": {}, \n' ' "field": null, \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "test1", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": null, \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') def test_delete(self): project = Project(self.storage, id='example') project.schemas # preload schemas item = Item( self.storage, id='1e47-4833-a4d4', sample=Sample( self.storage, id='1ddc-4043-ac4d', spider=Spider(self.storage, id='shop-crawler', project=project))) annotation = item.annotations['3606-4d68-a6a0|d1e2-4673-a72a'] annotation.delete() self.assertEqual(self.storage.open.call_count, 3) self.storage.open.assert_has_calls([ mock.call('items.json'), mock.call('spiders/shop-crawler.json'), mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json')]) self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('spiders/shop-crawler/1ddc-4043-ac4d.json', mock.ANY), mock.call('items.json', mock.ANY)]) self.storage.delete.assert_not_called() self.assertListEqual(list(item.annotations.keys()), ['5c18-40cf-8809|de35-49b5-b90b']) self.assertEqual( self.storage.files['spiders/shop-crawler/1ddc-4043-ac4d.json'], '{\n' ' "extractors": {}, \n' ' "id": "1ddc-4043-ac4d", \n' ' "name": "example", \n' ' "page_id": "ab5bbf650b32ca41af6f8e9976fc3c85eee87f67", \n' ' "page_type": "item", \n' ' "plugins": {\n' ' "annotations-plugin": {\n' ' "extracts": [\n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": null, \n' ' "id": "1e47-4833-a4d4#parent", \n' ' "item_container": true, \n' ' "repeated": false, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": "body", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "annotations": {\n' ' "#portia-content": "#dummy"\n' ' }, \n' ' "container_id": "1e47-4833-a4d4#parent", \n' ' "id": "1e47-4833-a4d4", \n' ' "item_container": true, \n' ' "repeated": true, \n' ' "required": [], \n' ' "schema_id": "1664-4f20-b657", \n' ' "selector": ".main", \n' ' "siblings": 0, \n' ' "tagid": null, \n' ' "text-content": "#portia-content"\n' ' }, \n' ' {\n' ' "accept_selectors": [\n' ' ".main:nth-child(1) > img"\n' ' ], \n' ' "container_id": "1e47-4833-a4d4", \n' ' "data": {\n' ' "de35-49b5-b90b": {\n' ' "attribute": "content", \n' ' "extractors": [\n' ' "e6fc-4758-9e6b", \n' ' "154f-45ce-bfbd"\n' ' ], \n' ' "field": "34bc-406f-80bc", \n' ' "required": false\n' ' }\n' ' }, \n' ' "id": "5c18-40cf-8809", \n' ' "text-content": "content", \n' ' "post_text": null, \n' ' "pre_text": null, \n' ' "reject_selectors": [], \n' ' "required": [], \n' ' "repeated": false, \n' ' "selection_mode": "auto", \n' ' "selector": ".main > img", \n' ' "tagid": null, \n' ' "xpath": null\n' ' }\n' ' ]\n' ' }\n' ' }, \n' ' "scrapes": "1664-4f20-b657", \n' ' "spider": "shop-crawler", \n' ' "url": "http://example.com", \n' ' "version": "' + SLYBOT_VERSION + '"\n' '}') self.assertEqual( self.storage.files['items.json'], '{\n' ' "1664-4f20-b657": {\n' ' "auto_created": true, \n' ' "fields": {\n' ' "cca5-490c-b604": {\n' ' "id": "cca5-490c-b604", \n' ' "name": "price", \n' ' "required": true, \n' ' "type": "price", \n' ' "vary": false\n' ' }, \n' ' "34bc-406f-80bc": {\n' ' "id": "34bc-406f-80bc", \n' ' "name": "image", \n' ' "required": false, \n' ' "type": "image", \n' ' "vary": false\n' ' }, \n' ' "ecfc-4dbe-b488": {\n' ' "id": "ecfc-4dbe-b488", \n' ' "name": "details", \n' ' "required": false, \n' ' "type": "text", \n' ' "vary": false\n' ' }\n' ' }, \n' ' "name": "product"\n' ' }, \n' ' "fa87-4791-8642": {\n' ' "fields": {}, \n' ' "name": "other"\n' ' }\n' '}') def test_invalid_project_name(self): self.assertRaises(ValidationError, Project, self.storage, id='') self.assertRaises(ValidationError, Project, self.storage, id='e' * 249) def test_invalid_spider_name(self): self.assertRaises(ValidationError, Spider, self.storage, id='') self.assertRaises(ValidationError, Spider, self.storage, id='e' * 244) ================================================ FILE: portia_server/portia_orm/tests/test_relationship.py ================================================ import json from unittest import mock from .models import (OneToOneModel1, OneToOneModel2, ParentModel, ChildModel, ManyToManyModel1, ManyToManyModel2, PolymorphicParentModel, PolymorphicChildModel1, PolymorphicChildModel2) from .utils import DataStoreTestCase, mock_storage class OneToOneRelationshipTests(DataStoreTestCase): def setUp(self): super(OneToOneRelationshipTests, self).setUp() self.storage = mock_storage({ 'o2o-model-1.json': '{' ' "id": "model-1",' ' "field": "model-1",' ' "m2": "model-2"' '}', 'o2o-model-2.json': '{' ' "id": "model-2",' ' "field": "model-2",' ' "m1": {' ' "id": "model-1",' ' "field": "model-1",' ' "m2": "model-2"' ' }' '}', }) def test_no_relation(self): model1 = OneToOneModel1(id='model-1') model2 = OneToOneModel2(id='model-2') self.assertEqual(model1.m2, None) self.assertEqual(model2.m1, None) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': None, }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': None, }) def test_set_relation(self): model1 = OneToOneModel1(id='model-1') model2 = OneToOneModel2(id='model-2') model2.m1 = model1 self.assertEqual(model1.m2, model2) self.assertEqual(model2.m1, model1) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': 'model-2', }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': { 'id': 'model-1', 'm2': 'model-2', }, }) def test_set_reverse_relation(self): model1 = OneToOneModel1(id='model-1') model2 = OneToOneModel2(id='model-2') model1.m2 = model2 self.assertEqual(model1.m2, model2) self.assertEqual(model2.m1, model1) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': 'model-2', }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': { 'id': 'model-1', 'm2': 'model-2', }, }) def test_create_with_relation(self): model1 = OneToOneModel1(id='model-1') model2 = OneToOneModel2(id='model-2', m1=model1) self.assertEqual(model1.m2, model2) self.assertEqual(model2.m1, model1) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': 'model-2', }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': { 'id': 'model-1', 'm2': 'model-2', }, }) def test_create_with_reverse_relation(self): model2 = OneToOneModel2(id='model-2') model1 = OneToOneModel1(id='model-1', m2=model2) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': 'model-2', }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': { 'id': 'model-1', 'm2': 'model-2', }, }) def test_change_relation(self): model1 = OneToOneModel1(id='model-1') model2 = OneToOneModel2(id='model-2', m1=model1) model3 = OneToOneModel1(id='model-3') self.assertEqual(model1.m2, model2) self.assertEqual(model2.m1, model1) self.assertEqual(model3.m2, None) model2.m1 = model3 self.assertEqual(model1.m2, None) self.assertEqual(model2.m1, model3) self.assertEqual(model3.m2, model2) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': { 'id': 'model-3', 'm2': 'model-2', }, }) def test_change_reverse_relation(self): model1 = OneToOneModel1(id='model-1') model2 = OneToOneModel2(id='model-2', m1=model1) model3 = OneToOneModel1(id='model-3') self.assertEqual(model1.m2, model2) self.assertEqual(model2.m1, model1) self.assertEqual(model3.m2, None) model3.m2 = model2 self.assertEqual(model1.m2, None) self.assertEqual(model2.m1, model3) self.assertEqual(model3.m2, model2) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': { 'id': 'model-3', 'm2': 'model-2', }, }) def test_load_full(self): model = OneToOneModel2(self.storage, id='model-2') self.assertEqual(model.dump(), { 'id': 'model-2', 'field': 'model-2', 'm1': { 'id': 'model-1', 'field': 'model-1', 'm2': 'model-2', }, }) self.storage.open.assert_called_once_with('o2o-model-2.json') def test_load_partial(self): model = OneToOneModel1(self.storage, id='model-1') self.assertEqual(model.dump(), { 'id': 'model-1', 'field': 'model-1', 'm2': 'model-2', }) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('o2o-model-1.json'), mock.call('o2o-model-2.json')]) def test_save_field(self): model1 = OneToOneModel1(self.storage, id='model-1') model2 = model1.m2 model1.field = 'changed-field-1' model2.field = 'changed-field-2' model2.save() self.assertEqual(self.storage.save.call_count, 1) self.storage.save.assert_has_calls([ mock.call('o2o-model-2.json', mock.ANY)]) self.assertEqual( self.storage.files['o2o-model-2.json'], '{\n' ' "field": "changed-field-2", \n' ' "id": "model-2", \n' ' "m1": {\n' ' "field": "model-1", \n' ' "id": "model-1", \n' ' "m2": "model-2"\n' ' }\n' '}') model1.save() self.assertEqual(self.storage.save.call_count, 3) self.storage.save.assert_has_calls([ mock.call('o2o-model-2.json', mock.ANY), mock.call('o2o-model-1.json', mock.ANY), mock.call('o2o-model-2.json', mock.ANY)]) self.assertEqual( self.storage.files['o2o-model-1.json'], '{\n' ' "field": "changed-field-1", \n' ' "id": "model-1", \n' ' "m2": "model-2"\n' '}') self.assertEqual( self.storage.files['o2o-model-2.json'], '{\n' ' "field": "changed-field-2", \n' ' "id": "model-2", \n' ' "m1": {\n' ' "field": "changed-field-1", \n' ' "id": "model-1", \n' ' "m2": "model-2"\n' ' }\n' '}') def test_save_id(self): model1 = OneToOneModel1(self.storage, id='model-1') model2 = model1.m2 model1.id = 'changed-id-1' model2.id = 'changed-id-2' model2.save() self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('o2o-model-2.json', mock.ANY), mock.call('o2o-model-1.json', mock.ANY)]) self.assertEqual( self.storage.files['o2o-model-1.json'], '{\n' ' "field": "model-1", \n' ' "id": "model-1", \n' ' "m2": "changed-id-2"\n' '}') self.assertEqual( self.storage.files['o2o-model-2.json'], '{\n' ' "field": "model-2", \n' ' "id": "changed-id-2", \n' ' "m1": {\n' ' "field": "model-1", \n' ' "id": "model-1", \n' ' "m2": "changed-id-2"\n' ' }\n' '}') model1.save() self.assertEqual(self.storage.save.call_count, 4) self.storage.save.assert_has_calls([ mock.call('o2o-model-2.json', mock.ANY), mock.call('o2o-model-1.json', mock.ANY), mock.call('o2o-model-1.json', mock.ANY), mock.call('o2o-model-2.json', mock.ANY)]) self.assertEqual( self.storage.files['o2o-model-1.json'], '{\n' ' "field": "model-1", \n' ' "id": "changed-id-1", \n' ' "m2": "changed-id-2"\n' '}') self.assertEqual( self.storage.files['o2o-model-2.json'], '{\n' ' "field": "model-2", \n' ' "id": "changed-id-2", \n' ' "m1": {\n' ' "field": "model-1", \n' ' "id": "changed-id-1", \n' ' "m2": "changed-id-2"\n' ' }\n' '}') class OneToManyRelationshipTests(DataStoreTestCase): def setUp(self): super(OneToManyRelationshipTests, self).setUp() self.storage = mock_storage({ 'parents.json': '{' ' "id": "parent-1",' ' "field": "parent-1",' ' "children": [' ' {' ' "id": "child-1",' ' "parent": "parent-1"' ' }' ' ]' '}', 'parent-1/children.json': '[' ' {' ' "id": "child-1",' ' "field": "child-1",' ' "parent": "parent-1"' ' }' ']', }) def test_no_children(self): parent = ParentModel(id='parent-1') self.assertEqual(len(parent.children), 0) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [], }) def test_set_children(self): parent = ParentModel(id='parent-1') child = ChildModel(id='child-1') parent.children = [child] self.assertEqual(child.parent, parent) self.assertEqual(len(parent.children), 1) self.assertEqual(parent.children[0], child) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'id': 'child-1', 'parent': 'parent-1', }, ], }) def test_add_to_children(self): parent = ParentModel(id='parent-1') child = ChildModel(id='child-1') parent.children.add(child) self.assertEqual(child.parent, parent) self.assertEqual(len(parent.children), 1) self.assertEqual(parent.children[0], child) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'id': 'child-1', 'parent': 'parent-1', }, ], }) def test_set_parent(self): parent = ParentModel(id='parent-1') child = ChildModel(id='child-1') child.parent = parent self.assertEqual(child.parent, parent) self.assertEqual(len(parent.children), 1) self.assertEqual(parent.children[0], child) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'id': 'child-1', 'parent': 'parent-1', }, ], }) def test_create_with_children(self): child = ChildModel(id='child-1') parent = ParentModel(id='parent-1', children=[child]) self.assertEqual(child.parent, parent) self.assertEqual(len(parent.children), 1) self.assertEqual(parent.children[0], child) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'id': 'child-1', 'parent': 'parent-1', }, ], }) def test_create_with_parent(self): parent = ParentModel(id='parent-1') child = ChildModel(id='child-1', parent=parent) self.assertEqual(child.parent, parent) self.assertEqual(len(parent.children), 1) self.assertEqual(parent.children[0], child) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'id': 'child-1', 'parent': 'parent-1', }, ], }) def test_change_parent(self): parent = ParentModel(id='parent-1') parent2 = ParentModel(id='parent-2') child = ChildModel(id='child-1', parent=parent) self.assertEqual(child.parent, parent) self.assertEqual(len(parent.children), 1) self.assertEqual(len(parent2.children), 0) child.parent = parent2 self.assertEqual(child.parent, parent2) self.assertEqual(len(parent.children), 0) self.assertEqual(len(parent2.children), 1) self.assertEqual(parent2.children[0], child) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [], }) self.assertEqual(parent2.dump(), { 'id': 'parent-2', 'children': [ { 'id': 'child-1', 'parent': 'parent-2', }, ], }) def test_change_children(self): parent = ParentModel(id='parent-1') child = ChildModel(id='child-1', parent=parent) child2 = ChildModel(id='child-2') self.assertEqual(child.parent, parent) self.assertEqual(child2.parent, None) self.assertEqual(len(parent.children), 1) parent.children = [child, child2] self.assertEqual(child.parent, parent) self.assertEqual(child2.parent, parent) self.assertEqual(len(parent.children), 2) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'id': 'child-1', 'parent': 'parent-1', }, { 'id': 'child-2', 'parent': 'parent-1', }, ], }) def test_getitem(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2, child3]) self.assertIs(parent.children[0], child1) self.assertIs(parent.children['child-1'], child1) self.assertIs(parent.children[child1], child1) with self.assertRaises(IndexError): parent.children[1000] with self.assertRaises(KeyError): parent.children['child-4'] self.assertEqual(parent.children[1:], [child2, child3]) def test_get(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2, child3]) self.assertIs(parent.children.get(0), child1) self.assertIs(parent.children.get('child-1'), child1) self.assertIs(parent.children.get(child1), child1) self.assertIs(parent.children.get('child-4'), None) sentinel = object() self.assertIs(parent.children.get('child-4', default=sentinel), sentinel) def test_setitem(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2, child3]) child1b = ChildModel(id='child-1') child1c = ChildModel(id='child-1') child1d = ChildModel(id='child-1') child4 = ChildModel(id='child-4') child5 = ChildModel(id='child-5') child6 = ChildModel(id='child-6') child7 = ChildModel(id='child-7') parent.children[0] = child1b self.assertIs(parent.children[0], child1b) parent.children['child-1'] = child1c self.assertIs(parent.children[0], child1c) parent.children[child1] = child1d self.assertIs(parent.children[0], child1d) self.assertListEqual(parent.children, [child1d, child2, child3]) parent.children[1:1] = [child4, child5] self.assertIs(child4.parent, parent) self.assertIs(child5.parent, parent) self.assertListEqual(parent.children, [child1d, child4, child5, child2, child3]) parent.children[:2] = [child6, child7] self.assertIs(child6.parent, parent) self.assertIs(child7.parent, parent) self.assertIs(child1d.parent, None) self.assertIs(child4.parent, None) self.assertListEqual(parent.children, [child6, child7, child5, child2, child3]) with self.assertRaises(ValueError): parent.children[0:0] = [child2] def test_delitem(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') child4 = ChildModel(id='child-4') child5 = ChildModel(id='child-5') parent = ParentModel(id='parent-1', children=[ child1, child2, child3, child4, child5]) del parent.children[0] del parent.children['child-3'] del parent.children[child4] self.assertListEqual(parent.children, [child2, child5]) self.assertIs(child1.parent, None) self.assertIs(child3.parent, None) self.assertIs(child4.parent, None) def test_append(self): child1 = ChildModel(id='child-1') child1b = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2]) parent.children.append(child3) self.assertListEqual(parent.children, [child1, child2, child3]) self.assertIs(child3.parent, parent) with self.assertRaises(ValueError): parent.children.append(child1b) def test_add(self): child1 = ChildModel(id='child-1') child1b = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2]) parent.children.add(child3) self.assertListEqual(parent.children, [child1, child2, child3]) self.assertIs(child3.parent, parent) parent.children.add(child1b) self.assertListEqual(parent.children, [child1, child2, child3]) def test_insert(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child2, child3]) parent.children.insert(0, child1) self.assertListEqual(parent.children, [child1, child2, child3]) self.assertIs(child1.parent, parent) def test_remove(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2, child3]) parent.children.remove(child1) self.assertListEqual(parent.children, [child2, child3]) self.assertIs(child1.parent, None) with self.assertRaises(ValueError): parent.children.remove(child1) def test_discard(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2, child3]) parent.children.discard(child1) self.assertListEqual(parent.children, [child2, child3]) self.assertIs(child1.parent, None) parent.children.discard(child1) self.assertListEqual(parent.children, [child2, child3]) def test_pop(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2, child3]) pop1 = parent.children.pop() self.assertIs(pop1, child3) self.assertListEqual(parent.children, [child1, child2]) self.assertIs(child3.parent, None) pop2 = parent.children.pop('child-1') self.assertIs(pop2, child1) self.assertListEqual(parent.children, [child2]) self.assertIs(child1.parent, None) def test_clear(self): child1 = ChildModel(id='child-1') child2 = ChildModel(id='child-2') child3 = ChildModel(id='child-3') parent = ParentModel(id='parent-1', children=[child1, child2, child3]) parent.children.clear() self.assertListEqual(parent.children, []) self.assertIs(child1.parent, None) self.assertIs(child2.parent, None) self.assertIs(child3.parent, None) def test_load_full(self): model = ParentModel(self.storage, id='parent-1') self.assertEqual(model.dump(), { 'id': 'parent-1', 'field': 'parent-1', 'children': [ { 'id': 'child-1', 'field': 'child-1', 'parent': 'parent-1', }, ], }) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('parents.json'), mock.call('parent-1/children.json')]) def test_load_partial(self): model = ChildModel(self.storage, id='child-1', parent=ParentModel(self.storage, id='parent-1')) self.assertEqual(model.dump(), { 'id': 'child-1', 'field': 'child-1', 'parent': 'parent-1', }) self.assertEqual(model, model.parent.children[0]) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('parents.json'), mock.call('parent-1/children.json')]) self.assertEqual(model.parent.dump(), { 'id': 'parent-1', 'field': 'parent-1', 'children': [ { 'id': 'child-1', 'field': 'child-1', 'parent': 'parent-1', }, ], }) def test_save_field(self): parent = ParentModel(self.storage, id='parent-1') child = parent.children[0] child.field = 'changed-id-1' parent.field = 'changed-id-2' parent.save() self.assertEqual(self.storage.save.call_count, 1) self.storage.save.assert_has_calls([ mock.call('parents.json', mock.ANY)]) self.assertEqual( self.storage.files['parents.json'], '{\n' ' "children": [\n' ' {\n' ' "field": "child-1", \n' ' "id": "child-1", \n' ' "parent": "parent-1"\n' ' }\n' ' ], \n' ' "field": "changed-id-2", \n' ' "id": "parent-1"\n' '}') child.save() self.assertEqual(self.storage.save.call_count, 3) self.storage.save.assert_has_calls([ mock.call('parents.json', mock.ANY), mock.call('parent-1/children.json', mock.ANY), mock.call('parents.json', mock.ANY)]) self.assertEqual( self.storage.files['parent-1/children.json'], '[\n' ' {\n' ' "field": "changed-id-1", \n' ' "id": "child-1", \n' ' "parent": "parent-1"\n' ' }\n' ']') self.assertEqual( self.storage.files['parents.json'], '{\n' ' "children": [\n' ' {\n' ' "field": "changed-id-1", \n' ' "id": "child-1", \n' ' "parent": "parent-1"\n' ' }\n' ' ], \n' ' "field": "changed-id-2", \n' ' "id": "parent-1"\n' '}') def test_save_id(self): parent = ParentModel(self.storage, id='parent-1') child = parent.children[0] child.id = 'changed-id-1' parent.id = 'changed-id-2' parent.save() self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('parents.json', mock.ANY), mock.call('changed-id-2/children.json', mock.ANY)]) self.storage.delete.assert_called_once_with('parent-1/children.json') self.assertEqual( self.storage.files['changed-id-2/children.json'], '[\n' ' {\n' ' "field": "child-1", \n' ' "id": "child-1", \n' ' "parent": "changed-id-2"\n' ' }\n' ']') self.assertEqual( self.storage.files['parents.json'], '{\n' ' "children": [\n' ' {\n' ' "field": "child-1", \n' ' "id": "child-1", \n' ' "parent": "changed-id-2"\n' ' }\n' ' ], \n' ' "field": "parent-1", \n' ' "id": "changed-id-2"\n' '}') child.save() self.assertEqual(self.storage.save.call_count, 4) self.storage.save.assert_has_calls([ mock.call('parents.json', mock.ANY), mock.call('changed-id-2/children.json', mock.ANY), mock.call('changed-id-2/children.json', mock.ANY), mock.call('parents.json', mock.ANY)]) self.assertEqual( self.storage.files['changed-id-2/children.json'], '[\n' ' {\n' ' "field": "child-1", \n' ' "id": "changed-id-1", \n' ' "parent": "changed-id-2"\n' ' }\n' ']') self.assertEqual( self.storage.files['parents.json'], '{\n' ' "children": [\n' ' {\n' ' "field": "child-1", \n' ' "id": "changed-id-1", \n' ' "parent": "changed-id-2"\n' ' }\n' ' ], \n' ' "field": "parent-1", \n' ' "id": "changed-id-2"\n' '}') class ManyToManyRelationshipTests(DataStoreTestCase): def setUp(self): super(ManyToManyRelationshipTests, self).setUp() self.storage = mock_storage({ 'm2m-model-1.json': '{' ' "id": "model-1",' ' "field": "model-1",' ' "m2": [' ' "model-2"' ' ]' '}', 'm2m-model-2.json': '[' ' {' ' "id": "model-2",' ' "field": "model-2",' ' "m1": [' ' {' ' "id": "model-1",' ' "field": "model-1",' ' "m2": [' ' "model-2"' ' ]' ' }' ' ]' ' }' ']', }) def test_no_relation(self): model1 = ManyToManyModel1(id='model-1') model2 = ManyToManyModel2(id='model-2') self.assertEqual(len(model1.m2), 0) self.assertEqual(len(model2.m1), 0) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [], }) def test_set_relation(self): model1 = ManyToManyModel1(id='model-1') model2 = ManyToManyModel2(id='model-2') model2.m1.append(model1) self.assertEqual(len(model1.m2), 1) self.assertEqual(model1.m2[0], model2) self.assertEqual(len(model2.m1), 1) self.assertEqual(model2.m1[0], model1) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [ 'model-2', ], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [ { 'id': 'model-1', 'm2': [ 'model-2', ], }, ], }) def test_set_reverse_relation(self): model1 = ManyToManyModel1(id='model-1') model2 = ManyToManyModel2(id='model-2') model1.m2.append(model2) self.assertEqual(len(model1.m2), 1) self.assertEqual(model1.m2[0], model2) self.assertEqual(len(model2.m1), 1) self.assertEqual(model2.m1[0], model1) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [ 'model-2', ], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [ { 'id': 'model-1', 'm2': [ 'model-2', ], }, ], }) def test_create_with_relation(self): model1 = ManyToManyModel1(id='model-1') model2 = ManyToManyModel2(id='model-2', m1=[model1]) self.assertEqual(len(model1.m2), 1) self.assertEqual(model1.m2[0], model2) self.assertEqual(len(model2.m1), 1) self.assertEqual(model2.m1[0], model1) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [ 'model-2', ], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [ { 'id': 'model-1', 'm2': [ 'model-2', ], }, ], }) def test_create_with_reverse_relation(self): model2 = ManyToManyModel2(id='model-2') model1 = ManyToManyModel1(id='model-1', m2=[model2]) self.assertEqual(len(model1.m2), 1) self.assertEqual(model1.m2[0], model2) self.assertEqual(len(model2.m1), 1) self.assertEqual(model2.m1[0], model1) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [ 'model-2', ], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [ { 'id': 'model-1', 'm2': [ 'model-2', ], }, ], }) def test_change_relation(self): model1 = ManyToManyModel1(id='model-1') model2 = ManyToManyModel2(id='model-2', m1=[model1]) model3 = ManyToManyModel1(id='model-3') self.assertEqual(len(model1.m2), 1) self.assertEqual(model1.m2[0], model2) self.assertEqual(len(model2.m1), 1) self.assertEqual(model2.m1[0], model1) self.assertEqual(len(model3.m2), 0) model2.m1.append(model3) self.assertEqual(len(model1.m2), 1) self.assertEqual(model1.m2[0], model2) self.assertEqual(len(model2.m1), 2) self.assertEqual(model2.m1[0], model1) self.assertEqual(model2.m1[1], model3) self.assertEqual(len(model3.m2), 1) self.assertEqual(model3.m2[0], model2) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [ 'model-2', ], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [ { 'id': 'model-1', 'm2': [ 'model-2', ], }, { 'id': 'model-3', 'm2': [ 'model-2', ], }, ], }) self.assertEqual(model3.dump(), { 'id': 'model-3', 'm2': [ 'model-2', ], }) model2.m1.remove(model1) self.assertEqual(len(model1.m2), 0) self.assertEqual(len(model2.m1), 1) self.assertEqual(model2.m1[0], model3) self.assertEqual(len(model3.m2), 1) self.assertEqual(model3.m2[0], model2) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [ { 'id': 'model-3', 'm2': [ 'model-2', ], }, ], }) self.assertEqual(model3.dump(), { 'id': 'model-3', 'm2': [ 'model-2', ], }) def test_change_reverse_relation(self): model1 = ManyToManyModel1(id='model-1') model2 = ManyToManyModel2(id='model-2', m1=[model1]) model3 = ManyToManyModel1(id='model-3') self.assertEqual(len(model1.m2), 1) self.assertEqual(model1.m2[0], model2) self.assertEqual(len(model2.m1), 1) self.assertEqual(model2.m1[0], model1) self.assertEqual(len(model3.m2), 0) model3.m2.append(model2) self.assertEqual(len(model1.m2), 1) self.assertEqual(model1.m2[0], model2) self.assertEqual(len(model2.m1), 2) self.assertEqual(model2.m1[0], model1) self.assertEqual(model2.m1[1], model3) self.assertEqual(len(model3.m2), 1) self.assertEqual(model3.m2[0], model2) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [ 'model-2', ], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [ { 'id': 'model-1', 'm2': [ 'model-2', ], }, { 'id': 'model-3', 'm2': [ 'model-2', ], }, ], }) self.assertEqual(model3.dump(), { 'id': 'model-3', 'm2': [ 'model-2', ], }) model1.m2.clear() self.assertEqual(len(model1.m2), 0) self.assertEqual(len(model2.m1), 1) self.assertEqual(model2.m1[0], model3) self.assertEqual(len(model3.m2), 1) self.assertEqual(model3.m2[0], model2) self.assertEqual(model1.dump(), { 'id': 'model-1', 'm2': [], }) self.assertEqual(model2.dump(), { 'id': 'model-2', 'm1': [ { 'id': 'model-3', 'm2': [ 'model-2', ], }, ], }) self.assertEqual(model3.dump(), { 'id': 'model-3', 'm2': [ 'model-2', ], }) def test_load_full(self): model = ManyToManyModel2(self.storage, id='model-2') self.assertEqual(model.dump(), { 'id': 'model-2', 'field': 'model-2', 'm1': [ { 'id': 'model-1', 'field': 'model-1', 'm2': [ 'model-2', ], }, ], }) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('m2m-model-2.json'), mock.call('m2m-model-1.json')]) def test_load_partial(self): model = ManyToManyModel1(self.storage, id='model-1') self.assertEqual(model.dump(), { 'id': 'model-1', 'field': 'model-1', 'm2': [ 'model-2', ], }) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('m2m-model-1.json'), mock.call('m2m-model-2.json')]) def test_save_field(self): model1 = ManyToManyModel1(self.storage, id='model-1') model2 = model1.m2[0] model1.field = 'changed-field-1' model2.field = 'changed-field-2' model2.save() self.storage.save.assert_called_once_with('m2m-model-2.json', mock.ANY) self.assertEqual( self.storage.files['m2m-model-2.json'], '[\n' ' {\n' ' "field": "changed-field-2", \n' ' "id": "model-2", \n' ' "m1": [\n' ' {\n' ' "field": "model-1", \n' ' "id": "model-1", \n' ' "m2": [\n' ' "model-2"\n' ' ]\n' ' }\n' ' ]\n' ' }\n' ']') model1.save() self.assertEqual(self.storage.save.call_count, 3) self.storage.save.assert_has_calls([ mock.call('m2m-model-2.json', mock.ANY), mock.call('m2m-model-1.json', mock.ANY), mock.call('m2m-model-2.json', mock.ANY)]) self.assertEqual( self.storage.files['m2m-model-1.json'], '{\n' ' "field": "changed-field-1", \n' ' "id": "model-1", \n' ' "m2": [\n' ' "model-2"\n' ' ]\n' '}') self.assertEqual( self.storage.files['m2m-model-2.json'], '[\n' ' {\n' ' "field": "changed-field-2", \n' ' "id": "model-2", \n' ' "m1": [\n' ' {\n' ' "field": "changed-field-1", \n' ' "id": "model-1", \n' ' "m2": [\n' ' "model-2"\n' ' ]\n' ' }\n' ' ]\n' ' }\n' ']') def test_save_id(self): model1 = ManyToManyModel1(self.storage, id='model-1') model2 = model1.m2[0] model1.id = 'changed-id-1' model2.id = 'changed-id-2' model2.save() self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('m2m-model-2.json', mock.ANY), mock.call('m2m-model-1.json', mock.ANY)]) self.assertEqual( self.storage.files['m2m-model-1.json'], '{\n' ' "field": "model-1", \n' ' "id": "model-1", \n' ' "m2": [\n' ' "changed-id-2"\n' ' ]\n' '}') self.assertEqual( self.storage.files['m2m-model-2.json'], '[\n' ' {\n' ' "field": "model-2", \n' ' "id": "changed-id-2", \n' ' "m1": [\n' ' {\n' ' "field": "model-1", \n' ' "id": "model-1", \n' ' "m2": [\n' ' "changed-id-2"\n' ' ]\n' ' }\n' ' ]\n' ' }\n' ']') model1.save() self.assertEqual(self.storage.save.call_count, 4) self.storage.save.assert_has_calls([ mock.call('m2m-model-2.json', mock.ANY), mock.call('m2m-model-1.json', mock.ANY), mock.call('m2m-model-1.json', mock.ANY), mock.call('m2m-model-2.json', mock.ANY)]) self.assertEqual( self.storage.files['m2m-model-1.json'], '{\n' ' "field": "model-1", \n' ' "id": "changed-id-1", \n' ' "m2": [\n' ' "changed-id-2"\n' ' ]\n' '}') self.assertEqual( self.storage.files['m2m-model-2.json'], '[\n' ' {\n' ' "field": "model-2", \n' ' "id": "changed-id-2", \n' ' "m1": [\n' ' {\n' ' "field": "model-1", \n' ' "id": "changed-id-1", \n' ' "m2": [\n' ' "changed-id-2"\n' ' ]\n' ' }\n' ' ]\n' ' }\n' ']') class PolymorphicRelationshipTests(DataStoreTestCase): def setUp(self): super(PolymorphicRelationshipTests, self).setUp() self.storage = mock_storage({ 'parents.json': '{' ' "id": "parent-1",' ' "field": "parent-1",' ' "children": [' ' {' ' "type": "PolymorphicChildModel1",' ' "id": "child-1"' ' },' ' {' ' "_type_": "PolymorphicChildModel2",' ' "id": "child-2"' ' }' ' ]' '}', 'children.json': '[' ' {' ' "type": "PolymorphicChildModel1",' ' "id": "child-1",' ' "field1": "child-1",' ' "parent": "parent-1"' ' },' ' {' ' "_type_": "PolymorphicChildModel2",' ' "id": "child-2",' ' "field2": "child-2",' ' "parent": "parent-1"' ' }' ']', }) def test_no_children(self): parent = PolymorphicParentModel(id='parent-1') self.assertEqual(len(parent.children), 0) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [], }) def test_set_children(self): parent = PolymorphicParentModel(id='parent-1') child1 = PolymorphicChildModel1(id='child-1', field1='field-1') child2 = PolymorphicChildModel2(id='child-2', field2='field-2') parent.children = [child1, child2] self.assertEqual(child1.parent, parent) self.assertEqual(child2.parent, parent) self.assertEqual(len(parent.children), 2) self.assertEqual(parent.children[0], child1) self.assertEqual(parent.children[1], child2) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, ], }) def test_add_to_children(self): parent = PolymorphicParentModel(id='parent-1') child1 = PolymorphicChildModel1(id='child-1', field1='field-1') child2 = PolymorphicChildModel2(id='child-2', field2='field-2') parent.children.add(child2) parent.children.add(child1) self.assertEqual(child1.parent, parent) self.assertEqual(child2.parent, parent) self.assertEqual(len(parent.children), 2) self.assertEqual(parent.children[0], child2) self.assertEqual(parent.children[1], child1) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, ], }) def test_set_parent(self): parent = PolymorphicParentModel(id='parent-1') child1 = PolymorphicChildModel1(id='child-1', field1='field-1') child2 = PolymorphicChildModel2(id='child-2', field2='field-2') child1.parent = parent child2.parent = parent self.assertEqual(child1.parent, parent) self.assertEqual(child2.parent, parent) self.assertEqual(len(parent.children), 2) self.assertEqual(parent.children[0], child1) self.assertEqual(parent.children[1], child2) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, ], }) def test_create_with_children(self): child1 = PolymorphicChildModel1(id='child-1', field1='field-1') child2 = PolymorphicChildModel2(id='child-2', field2='field-2') parent = PolymorphicParentModel(id='parent-1', children=[child1, child2]) self.assertEqual(child1.parent, parent) self.assertEqual(child2.parent, parent) self.assertEqual(len(parent.children), 2) self.assertEqual(parent.children[0], child1) self.assertEqual(parent.children[1], child2) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, ], }) def test_create_with_parent(self): parent = PolymorphicParentModel(id='parent-1') child1 = PolymorphicChildModel1(id='child-1', field1='field-1', parent=parent) child2 = PolymorphicChildModel2(id='child-2', field2='field-2', parent=parent) self.assertEqual(child1.parent, parent) self.assertEqual(child2.parent, parent) self.assertEqual(len(parent.children), 2) self.assertEqual(parent.children[0], child1) self.assertEqual(parent.children[1], child2) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, ], }) def test_change_parent(self): parent1 = PolymorphicParentModel(id='parent-1') parent2 = PolymorphicParentModel(id='parent-2') child1 = PolymorphicChildModel1(id='child-1', field1='field-1', parent=parent1) child2 = PolymorphicChildModel2(id='child-2', field2='field-2', parent=parent1) self.assertEqual(child1.parent, parent1) self.assertEqual(child2.parent, parent1) self.assertEqual(len(parent1.children), 2) self.assertEqual(len(parent2.children), 0) child2.parent = parent2 self.assertEqual(child1.parent, parent1) self.assertEqual(child2.parent, parent2) self.assertEqual(len(parent1.children), 1) self.assertEqual(len(parent2.children), 1) self.assertEqual(parent1.children[0], child1) self.assertEqual(parent2.children[0], child2) self.assertEqual(parent1.dump(), { 'id': 'parent-1', 'children': [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, ], }) self.assertEqual(parent2.dump(), { 'id': 'parent-2', 'children': [ { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, ], }) child1.parent = parent2 self.assertEqual(child1.parent, parent2) self.assertEqual(child2.parent, parent2) self.assertEqual(len(parent1.children), 0) self.assertEqual(len(parent2.children), 2) self.assertEqual(parent2.children[0], child2) self.assertEqual(parent2.children[1], child1) self.assertEqual(parent1.dump(), { 'id': 'parent-1', 'children': [], }) self.assertEqual(parent2.dump(), { 'id': 'parent-2', 'children': [ { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, ], }) def test_change_children(self): parent = PolymorphicParentModel(id='parent-1') child1 = PolymorphicChildModel1(id='child-1', field1='field-1', parent=parent) child2 = PolymorphicChildModel2(id='child-2', field2='field-2') self.assertEqual(child1.parent, parent) self.assertEqual(child2.parent, None) self.assertEqual(len(parent.children), 1) parent.children = [child1, child2] self.assertEqual(child1.parent, parent) self.assertEqual(child2.parent, parent) self.assertEqual(len(parent.children), 2) self.assertEqual(parent.dump(), { 'id': 'parent-1', 'children': [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, ], }) def test_getitem(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel2(id='child-2') child3 = PolymorphicChildModel1(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2, child3]) self.assertIs(parent.children[0], child1) self.assertIs(parent.children['child-1'], child1) self.assertIs(parent.children[child1], child1) self.assertIs(parent.children[1], child2) self.assertIs(parent.children['child-2'], child2) self.assertIs(parent.children[child2], child2) with self.assertRaises(IndexError): parent.children[1000] with self.assertRaises(KeyError): parent.children['child-4'] self.assertEqual(parent.children[2:], [child3]) def test_get(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel2(id='child-2') child3 = PolymorphicChildModel1(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2, child3]) self.assertIs(parent.children.get(0), child1) self.assertIs(parent.children.get('child-1'), child1) self.assertIs(parent.children.get(child1), child1) self.assertIs(parent.children.get(1), child2) self.assertIs(parent.children.get('child-2'), child2) self.assertIs(parent.children.get(child2), child2) self.assertIs(parent.children.get('child-4'), None) sentinel = object() self.assertIs(parent.children.get('child-4', default=sentinel), sentinel) def test_setitem(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel2(id='child-2') child3 = PolymorphicChildModel1(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2, child3]) child1b = PolymorphicChildModel1(id='child-1') child1c = PolymorphicChildModel1(id='child-1') child1d = PolymorphicChildModel1(id='child-1') child4 = PolymorphicChildModel2(id='child-4') child5 = PolymorphicChildModel1(id='child-5') child6 = PolymorphicChildModel2(id='child-6') child7 = PolymorphicChildModel1(id='child-7') parent.children[0] = child1b self.assertIs(parent.children[0], child1b) parent.children['child-1'] = child1c self.assertIs(parent.children[0], child1c) parent.children[child1] = child1d self.assertIs(parent.children[0], child1d) self.assertListEqual(parent.children, [child1d, child2, child3]) parent.children[1:1] = [child4, child5] self.assertIs(child4.parent, parent) self.assertIs(child5.parent, parent) self.assertListEqual(parent.children, [child1d, child4, child5, child2, child3]) parent.children[:2] = [child6, child7] self.assertIs(child6.parent, parent) self.assertIs(child7.parent, parent) self.assertIs(child1d.parent, None) self.assertIs(child4.parent, None) self.assertListEqual(parent.children, [child6, child7, child5, child2, child3]) with self.assertRaises(ValueError): parent.children[0:0] = [child2] def test_delitem(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel2(id='child-2') child3 = PolymorphicChildModel1(id='child-3') child4 = PolymorphicChildModel2(id='child-4') child5 = PolymorphicChildModel1(id='child-5') parent = PolymorphicParentModel(id='parent-1', children=[ child1, child2, child3, child4, child5]) del parent.children[0] del parent.children['child-3'] del parent.children[child4] self.assertListEqual(parent.children, [child2, child5]) self.assertIs(child1.parent, None) self.assertIs(child3.parent, None) self.assertIs(child4.parent, None) def test_append(self): child1 = PolymorphicChildModel1(id='child-1') child1b = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel1(id='child-2') child3 = PolymorphicChildModel2(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2]) parent.children.append(child3) self.assertListEqual(parent.children, [child1, child2, child3]) self.assertIs(child3.parent, parent) with self.assertRaises(ValueError): parent.children.append(child1b) def test_add(self): child1 = PolymorphicChildModel1(id='child-1') child1b = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel1(id='child-2') child3 = PolymorphicChildModel2(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2]) parent.children.add(child3) self.assertListEqual(parent.children, [child1, child2, child3]) self.assertIs(child3.parent, parent) parent.children.add(child1b) self.assertListEqual(parent.children, [child1, child2, child3]) def test_insert(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel1(id='child-2') child3 = PolymorphicChildModel1(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child2, child3]) parent.children.insert(0, child1) self.assertListEqual(parent.children, [child1, child2, child3]) self.assertIs(child1.parent, parent) def test_remove(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel1(id='child-2') child3 = PolymorphicChildModel1(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2, child3]) parent.children.remove(child1) self.assertListEqual(parent.children, [child2, child3]) self.assertIs(child1.parent, None) with self.assertRaises(ValueError): parent.children.remove(child1) def test_discard(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel1(id='child-2') child3 = PolymorphicChildModel1(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2, child3]) parent.children.discard(child1) self.assertListEqual(parent.children, [child2, child3]) self.assertIs(child1.parent, None) parent.children.discard(child1) self.assertListEqual(parent.children, [child2, child3]) def test_pop(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel1(id='child-2') child3 = PolymorphicChildModel1(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2, child3]) pop1 = parent.children.pop() self.assertIs(pop1, child3) self.assertListEqual(parent.children, [child1, child2]) self.assertIs(child3.parent, None) pop2 = parent.children.pop('child-1') self.assertIs(pop2, child1) self.assertListEqual(parent.children, [child2]) self.assertIs(child1.parent, None) def test_clear(self): child1 = PolymorphicChildModel1(id='child-1') child2 = PolymorphicChildModel1(id='child-2') child3 = PolymorphicChildModel1(id='child-3') parent = PolymorphicParentModel( id='parent-1', children=[child1, child2, child3]) parent.children.clear() self.assertListEqual(parent.children, []) self.assertIs(child1.parent, None) self.assertIs(child2.parent, None) self.assertIs(child3.parent, None) def test_load_full(self): model = PolymorphicParentModel(self.storage, id='parent-1') self.assertEqual(model.dump(), { 'id': 'parent-1', 'field': 'parent-1', 'children': [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, ], }) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('parents.json'), mock.call('children.json')]) def test_load_partial(self): model = PolymorphicChildModel1( self.storage, id='child-1', parent=PolymorphicParentModel( self.storage, id='parent-1')) self.assertEqual(model.dump(), { 'type': 'PolymorphicChildModel1', 'id': 'child-1', 'field1': 'child-1', 'parent': 'parent-1', }) self.assertEqual(model, model.parent.children[0]) self.assertEqual(self.storage.open.call_count, 2) self.storage.open.assert_has_calls([ mock.call('parents.json'), mock.call('children.json')]) self.assertEqual(model.parent.dump(), { 'children': [ { 'type': 'PolymorphicChildModel1', 'id': 'child-1', }, { '_type_': 'PolymorphicChildModel2', 'id': 'child-2', }, ], 'field': 'parent-1', 'id': 'parent-1', }) def test_save_field(self): parent = PolymorphicParentModel(self.storage, id='parent-1') child = parent.children[0] child.field1 = 'changed-id-1' parent.field = 'changed-id-2' parent.save() self.assertEqual(self.storage.save.call_count, 1) self.storage.save.assert_has_calls([ mock.call('parents.json', mock.ANY)]) self.assertEqual( self.storage.files['parents.json'], '{\n' ' "children": [\n' ' {\n' ' "id": "child-1", \n' ' "type": "PolymorphicChildModel1"\n' ' }, \n' ' {\n' ' "_type_": "PolymorphicChildModel2", \n' ' "id": "child-2"\n' ' }\n' ' ], \n' ' "field": "changed-id-2", \n' ' "id": "parent-1"\n' '}') child.save() self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('parents.json', mock.ANY), mock.call('children.json', mock.ANY)]) self.assertEqual( self.storage.files['children.json'], '[\n' ' {\n' ' "field1": "changed-id-1", \n' ' "id": "child-1", \n' ' "parent": "parent-1", \n' ' "type": "PolymorphicChildModel1"\n' ' }, \n' ' {\n' ' "_type_": "PolymorphicChildModel2", \n' ' "field2": "child-2", \n' ' "id": "child-2", \n' ' "parent": "parent-1"\n' ' }\n' ']') def test_save_id(self): parent = PolymorphicParentModel(self.storage, id='parent-1') child = parent.children[0] child.id = 'changed-id-1' parent.id = 'changed-id-2' parent.save() self.assertEqual(self.storage.save.call_count, 2) self.storage.save.assert_has_calls([ mock.call('parents.json', mock.ANY), mock.call('children.json', mock.ANY)]) self.assertEqual( self.storage.files['parents.json'], '{\n' ' "children": [\n' ' {\n' ' "id": "child-1", \n' ' "type": "PolymorphicChildModel1"\n' ' }, \n' ' {\n' ' "_type_": "PolymorphicChildModel2", \n' ' "id": "child-2"\n' ' }\n' ' ], \n' ' "field": "parent-1", \n' ' "id": "changed-id-2"\n' '}') self.assertEqual( self.storage.files['children.json'], '[\n' ' {\n' ' "field1": "child-1", \n' ' "id": "child-1", \n' ' "parent": "changed-id-2", \n' ' "type": "PolymorphicChildModel1"\n' ' }, \n' ' {\n' ' "_type_": "PolymorphicChildModel2", \n' ' "field2": "child-2", \n' ' "id": "child-2", \n' ' "parent": "changed-id-2"\n' ' }\n' ']') child.save() self.assertEqual(self.storage.save.call_count, 4) self.storage.save.assert_has_calls([ mock.call('parents.json', mock.ANY), mock.call('children.json', mock.ANY), mock.call('children.json', mock.ANY), mock.call('parents.json', mock.ANY)]) self.assertEqual( self.storage.files['children.json'], '[\n' ' {\n' ' "field1": "child-1", \n' ' "id": "changed-id-1", \n' ' "parent": "changed-id-2", \n' ' "type": "PolymorphicChildModel1"\n' ' }, \n' ' {\n' ' "_type_": "PolymorphicChildModel2", \n' ' "field2": "child-2", \n' ' "id": "child-2", \n' ' "parent": "changed-id-2"\n' ' }\n' ']') self.assertEqual( self.storage.files['parents.json'], '{\n' ' "children": [\n' ' {\n' ' "id": "changed-id-1", \n' ' "type": "PolymorphicChildModel1"\n' ' }, \n' ' {\n' ' "_type_": "PolymorphicChildModel2", \n' ' "id": "child-2"\n' ' }\n' ' ], \n' ' "field": "parent-1", \n' ' "id": "changed-id-2"\n' '}') ================================================ FILE: portia_server/portia_orm/tests/utils.py ================================================ import errno import unittest from unittest import mock from storage.backends import ContentFile from ..datastore import data_store_context class DataStoreTestCase(unittest.TestCase): def setUp(self): context_manager = data_store_context() self.addCleanup(context_manager.__exit__, None, None, None) context_manager.__enter__() def mock_storage(files): def exists(name): return name in files def open_(name, *args, **kwargs): try: data = files[name] except KeyError: raise IOError(2, 'No file or directory', name) return ContentFile(data, name) def open_with_default(name, default=None, *args, **kwargs): try: return open_(name, *args, **kwargs) except IOError as error: if error.errno == errno.ENOENT: return ContentFile(json.dumps(default), name) raise error def save(name, content): files[name] = content.read() def delete(name): try: del files[name] except KeyError: raise IOError(2, 'No file or directory', name) def listdir(path): path = path.rstrip('/') + '/' dir_set, file_set = set(), set() for p in files.keys(): if not p.startswith(path): continue parts = p[len(path):].split('/') if len(parts) == 1: file_set.add(parts[0]) else: dir_set.add(parts[0]) return sorted(dir_set), sorted(file_set) storage = mock.MagicMock() storage.name = 'example' storage.files = files storage.exists.side_effect = exists storage.open.side_effect = open_ storage.open_with_default.side_effect = open_with_default storage.save.side_effect = save storage.delete.side_effect = delete storage.listdir.side_effect = listdir return storage ================================================ FILE: portia_server/portia_orm/utils.py ================================================ from collections import OrderedDict from itertools import islice from uuid import uuid4 from django.utils.functional import cached_property from six import iteritems from .exceptions import ValidationError __all__ = [ 'cached_property', 'cached_property_ignore_set', 'class_property', 'short_guid', 'unspecified', 'uuid4', 'validate_type', 'AttributeDict', 'OrderedIndexedTransformDict', ] JSON_LEN = len('.json') _SENTINEL = object() class cached_property_ignore_set(cached_property): def __set__(self, instance, value): pass class class_property(object): """A read-only descriptor that works on the class too""" def __init__(self, fget=None): if fget is not None and not isinstance(fget, classmethod): fget = classmethod(fget) self.fget = fget def __get__(self, instance, instance_type=None): return self.fget.__get__(instance, instance_type)() def short_guid(): return '-'.join(str(uuid4()).split('-')[1:4]) unspecified = object() def validate_type(value, model): if not isinstance(value, model): raise ValidationError( "'{!r}' is not an instance of type '{}'".format( value, model.__name__)) def unwrap_envelopes(data, many, pk_field, remove_key): unwrapped = [] for pk, obj in iteritems(data): if not remove_key: try: if obj[pk_field] != pk: raise ValidationError( u"Envelope id does not match value of primary key " u"field") except KeyError: pass obj[pk_field] = pk unwrapped.append(obj) if not many and len(unwrapped) == 1: return unwrapped[0] return unwrapped def wrap_envelopes(data, many, pk_field, remove_key): if not many: data = [data] wrapped = OrderedDict() for obj in data: pk = obj[pk_field] if remove_key: del obj[pk_field] wrapped[pk] = obj return wrapped class AttributeDict(dict): def __getattr__(self, name): try: return self[name] except KeyError: raise AttributeError( u"'{}' object has no attribute '{}'".format( self.__class__.__name__, name)) def strip_json(fname): if fname.endswith('.json'): return fname[:-JSON_LEN] return fname class OrderedIndexedTransformDict(object): __slots__ = ('_transform', '_data') def __init__(self, transform, init_dict=None, **kwargs): if not callable(transform): raise TypeError('expected callable, got %r' % transform.__class__) self._transform = transform self._data = OrderedDict() if init_dict: self.update(init_dict) if kwargs: self.update(kwargs) def getitem(self, key): transformed = self._transform(key) value = self._data[transformed] return transformed, value def __len__(self): return len(self._data) def __iter__(self): return iter(self._data.keys()) def __getitem__(self, key): try: return self._data[key] except KeyError: return self._data[self._transform(key)] def __setitem__(self, key, value=None): transformed = self._transform(key) self._data[transformed] = len(self._data) def __delitem__(self, key): if hasattr(key, 'indices'): data_len = len(self._data) indices = key.indices(len(self)) if data_len <= len(range(*indices)): self._data = OrderedDict() return keys_to_remove = list(islice(self._data.keys(), *indices)) for key in keys_to_remove: del self._data[key] self._data = OrderedDict((k, i) for i, k in enumerate(self._data)) else: transformed = self._transform(key) self._remove(transformed) del self._data[transformed] def clear(self): self._data.clear() def __contains__(self, key): return self._transform(key) in self._data def get(self, key, default=None): return self._data.get(self._transform(key), default) def pop(self, key, default=_SENTINEL): transformed = self._transform(key) self._remove(transformed) if default is _SENTINEL: return self._data.pop(transformed) else: return self._data.pop(transformed, default) def items(self): return self._data.items() def update(self, value, **kws): self._data.update(value, **kws) def insert(self, index, value): data = self._data for k, v in data.items(): if v >= index: data[k] += 1 data[value] = index def replace(self, key, value): key = self._transform(key) value = self._transform(value) if key == value: return self._data = OrderedDict((value if k == key else k, i) for k, i in self._data.items()) def _remove(self, key): data = self._data if key not in data: return index = data[key] for key, value in data.items(): if value > index: data[key] = value - 1 def popitem(self): transformed, value = self._data.popitem() return transformed, value def copy(self): other = self.__class__(self._transform) other._data = self._data.copy() return other __copy__ = copy def __getstate__(self): return self._transform, self._data def __setstate__(self, state): self._transform, self._data = state def __repr__(self): try: equiv = dict(self) except TypeError: # Some keys are unhashable, fall back on .items() equiv = list(self.items()) return '{}({!r}, {})'.format(self.__class__.__name__, self._transform, equiv) ================================================ FILE: portia_server/portia_orm/validators.py ================================================ from marshmallow.validate import (ContainsOnly, Range, Regexp, Predicate, NoneOf, OneOf) __all__ = [ 'ContainsOnly', 'Range', 'Regexp', 'Predicate', 'NoneOf', 'OneOf' ] ================================================ FILE: portia_server/portia_server/__init__.py ================================================ ================================================ FILE: portia_server/portia_server/backends.py ================================================ from .models import LocalUser class LocalAuthentication(object): def authenticate(self, request, **kwargs): return LocalUser(**kwargs), None def get_user(self, user_id): # fall through and let the middleware add the user again return None ================================================ FILE: portia_server/portia_server/models.py ================================================ from __future__ import unicode_literals import getpass import socket from django.db.models.fields import CharField from django.contrib.auth.models import AnonymousUser from django.utils.encoding import python_2_unicode_compatible @python_2_unicode_compatible class LocalUser(AnonymousUser): is_active = True default_username = getpass.getuser() # add this so that the methods in django.contrib.auth that expect a user # model with a pk field work correctly class _meta: pk = CharField() pk.set_attributes_from_name('pk') def __init__(self, **kwargs): super(LocalUser, self).__init__() self.username = kwargs.get('username', self.default_username) try: self.id except AttributeError: self.id = None @property def pk(self): return self.id def __str__(self): return 'LocalUser({})'.format(self.username) def __eq__(self, other): return isinstance(other, self.__class__) and other.id == self.id def __hash__(self): hash(self.id) def is_anonymous(self): return False def is_authenticated(self): return True def save(self, *args, **kwargs): pass ================================================ FILE: portia_server/portia_server/settings.py ================================================ """ Django settings for portia_server project. Generated by 'django-admin startproject' using Django 1.9.7. For more information on this file, see https://docs.djangoproject.com/en/1.9/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.9/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) STATIC_ROOT = os.path.realpath(os.path.join(BASE_DIR, '../portiaui/dist')) STATIC_URL = '/' STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' MEDIA_ROOT = os.path.abspath(os.path.join(BASE_DIR, '../data/projects')) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'x8#v=v_yen3pvul&2*-x3=td2eqvw%5!*qaf^g8vzu#gcyo+%n' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [ '*' ] # Application definition INSTALLED_APPS = [ 'db_repo.apps.DbRepoConfig', 'storage.apps.StorageConfig', 'portia_orm.apps.PortiaOrmConfig', 'portia_api.apps.PortiaApiConfig', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'portia_orm.middleware.ORMDataStoreMiddleware', ] ROOT_URLCONF = 'portia_server.urls' WSGI_APPLICATION = 'portia_server.wsgi.application' # Database # https://docs.djangoproject.com/en/1.9/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.9/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True PORTIA_STORAGE_BACKEND = os.environ.get('PORTIA_STORAGE_BACKEND', 'storage.backends.FsStorage') REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'portia_server.backends.LocalAuthentication', ), 'EXCEPTION_HANDLER': 'portia_api.jsonapi.exceptions.jsonapi_exception_handler', 'URL_FORMAT_OVERRIDE': None } CUSTOM = {} CAPABILITIES = { 'version_control': False, 'create_projects': True, 'delete_projects': True, 'rename_projects': True, 'deploy_projects': True, 'rename_spiders': True, 'rename_templates': True, } # domains that portia will not load BLACKLIST_URLS = set() # Schedule and deploy settings PROJECT_DEPLOYER = os.environ.get( 'PROJECT_DEPLOYER', 'portia_api.utils.deploy.scrapyd.ScrapydDeploy') # Function or object to generate version for deploy DEPLOY_VERSION = None # Scrapyd Deploy settings # Path to default scrapyd cfg file SCRAPYD_CFG_DEFAULT = os.environ.get('SCRAPYD_CFG_DEFAULT', None) # Base API url for scrapyd instance SCRAPYD_URL = os.environ.get('SCRAPYD_URL', 'http://localhost:6800/') SCRAPYD_USERNAME = os.environ.get('SCRAPYD_USERNAME') SCRAPYD_PASSWORD = os.environ.get('SCRAPYD_PASSWORD') # Scrapinghub Deploy settings SCRAPINGHUB_APIKEY = (os.environ.get('SCRAPINGHUB_APIKEY') or os.environ.get('SHUB_APIKEY')) ================================================ FILE: portia_server/portia_server/urls.py ================================================ from django.conf.urls import url, include from . import views from portia_api import urls urlpatterns = [ url(r'^api/', include((urls, 'api'), namespace='api')), url(r'^server_capabilities$', views.capabilities), ] ================================================ FILE: portia_server/portia_server/views.py ================================================ from django.conf import settings from portia_api.jsonapi import JSONResponse def capabilities(request): capabilities = { 'custom': settings.CUSTOM, 'username': request.user.username, 'capabilities': settings.CAPABILITIES, } return JSONResponse(capabilities) ================================================ FILE: portia_server/portia_server/wsgi.py ================================================ """ WSGI config for portia_server project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "portia_server.settings") application = get_wsgi_application() ================================================ FILE: portia_server/requirements.txt ================================================ crochet==1.9.0 django>=1.11.21 django-cache-machine==1.0.0 djangorestframework==3.7.7 dj-database-url==0.5.0 drf-nested-routers==0.11.1 dulwich==0.18.6 marshmallow==2.8.0 marshmallow_jsonapi==0.10.0 mysqlclient==1.3.12 requests>=2.20.0 toposort==1.5 whitenoise==3.3.1 portia2code==0.0.17 shub==2.7.0 ================================================ FILE: portia_server/storage/__init__.py ================================================ from django.conf import settings from django.utils.module_loading import import_string __all__ = [ 'get_storage_class', 'create_project_storage', ] storage_class = None def get_storage_class(): global storage_class if storage_class is None and settings.PORTIA_STORAGE_BACKEND: storage_class = import_string(settings.PORTIA_STORAGE_BACKEND) storage_class.setup() return storage_class def create_project_storage(project_id, author=None, branch=None): storage_class = get_storage_class() return storage_class(project_id, author=author) ================================================ FILE: portia_server/storage/apps.py ================================================ from django.apps import AppConfig class StorageConfig(AppConfig): name = 'storage' ================================================ FILE: portia_server/storage/backends.py ================================================ import errno import json import logging import os import os.path import re import shutil import six import sys from collections import OrderedDict from django.conf import settings from django.core.files.base import ContentFile from django.core.files.move import file_move_safe from django.core.files.storage import FileSystemStorage, Storage try: from dulwich.diff_tree import tree_changes from dulwich.objects import Blob, Tree from dulwich.errors import ObjectMissing except ImportError: pass # Dulwich not required when using FS backend from six import iteritems, text_type, string_types from .projecttemplates import templates try: from .repoman import Repoman, DEFAULT_USER, FILE_MODE except ImportError: pass # Repoman not required when using FS backend logger = logging.getLogger(__name__) class InvalidFilename(Exception): pass class CommittingStorage(object): version_control = False create_projects = True delete_projects = True rename_projects = True deploy_projects = False rename_spiders = True rename_samples = True default_files = { 'project.json': 'PROJECT', 'scrapy.cfg': 'SCRAPY', 'setup.py': 'SETUP', 'items.json': 'ITEMS', 'extractors.json': 'EXTRACTORS', os.path.join('spiders', '__init__.py'): None, os.path.join('spiders', 'settings.py'): 'SETTINGS', } def init_project(self): self.validate_filename(self.name) for filename, templatename in iteritems(self.default_files): if not self.exists(filename): template = templates.get(templatename, '') % { 'name': self.name, } self.save(filename, ContentFile(template, filename)) @classmethod def get_projects(cls, user): # return an OrderedDict of id => name pairs try: dirs, _ = cls('').listdir('') return OrderedDict((project, project) for project in dirs) except OSError as ex: if ex.errno != errno.ENOENT: six.reraise(*sys.exc_info()) @classmethod def setup(cls): pass def get_available_name(self, name, max_length=None): return name def commit(self, message='Saving multiple files'): pass def changed_files(self): return [] class BasePortiaStorage(CommittingStorage, Storage): def __init__(self, name, author=None): self.name = text_type(name) @staticmethod def is_valid_filename(s): # based on Django's Storage.get_valid_filename if s.strip() != s: return False if re.sub(r'(?u)[^- \w.]', '', s) != s: return False return True @classmethod def validate_filename(cls, s): s = text_type(s) if not cls.is_valid_filename(s): raise InvalidFilename( u"The string '{}' is not a valid filename.".format(s)) return s def open_with_default(self, name, default=None): try: return self.open(name, mode='r') except IOError as error: if error.errno == errno.ENOENT: return ContentFile(json.dumps(default), name) raise error class FsStorage(BasePortiaStorage, FileSystemStorage): base_dir = settings.MEDIA_ROOT def __init__(self, name, author=None, *args, **kwargs): self.author = author super(FsStorage, self).__init__(name, *args, **kwargs) FileSystemStorage.__init__(self, os.path.join( self.base_dir, self.name)) if name: self.init_project() def isdir(self, name): return os.path.isdir(self.path(name)) def isfile(self, name): return os.path.isfile(self.path(name)) def move(self, old_file_name, new_file_name, allow_overwrite=False): if self.isdir(old_file_name): shutil.move(self.path(old_file_name), self.path(new_file_name)) else: file_move_safe(self.path(old_file_name), self.path(new_file_name), allow_overwrite=True) def rmtree(self, name): shutil.rmtree(self.path(name)) def _save(self, name, content): # Taken from django.core.files.storage.FileSystemStorage._save # Need to allow overwrite full_path = self.path(name) directory = os.path.dirname(full_path) if not os.path.exists(directory): try: if self.directory_permissions_mode is not None: # os.makedirs applies the global umask, so we reset it, # for consistency with file_permissions_mode behavior. old_umask = os.umask(0) try: os.makedirs(directory, self.directory_permissions_mode) finally: os.umask(old_umask) else: os.makedirs(directory) except OSError as e: if e.errno != errno.EEXIST: six.reraise(*sys.exc_info()) if not os.path.isdir(directory): raise IOError("%s exists and is not a directory." % directory) try: _file = None for chunk in content.chunks(): if _file is None: mode = 'wb' if isinstance(chunk, bytes) else 'wt' _file = open(full_path, mode) _file.write(chunk) finally: if _file is not None: _file.close() if self.file_permissions_mode is not None: os.chmod(full_path, self.file_permissions_mode) return name def delete(self, name): super(FsStorage, self).delete(name) name = self.path(name) if name.endswith('.json'): dir_path = name[:-len('.json')] if self.isdir(dir_path): self.rmtree(dir_path) class GitStorage(BasePortiaStorage): version_control = True def __init__(self, name, author=None): super(GitStorage, self).__init__(name) if not name: return self._tree, self._working_tree = None, None self.author = author repo = Repoman.open_repo(name, author) self.repo = repo self.branch = branch = (author and author.username) or DEFAULT_USER self.checkout(branch=branch) self.init_project() def checkout(self, commit=None, branch=None, retry=True): if commit is not None and isinstance(commit, string_types): commit = self.repo._repo.get_object(commit) if not commit: branches = OrderedDict((('refs/heads/%s' % branch or 'master', 1), ('refs/heads/master', 1))) for ref in branches: try: _commit_id = self.repo._repo.refs[ref] except KeyError: pass else: try: commit = self.repo._repo.get_object(_commit_id) except ObjectMissing: if ref != 'refs/heads/master': del self.repo._repo.refs[ref] else: six.reraise(*sys.exc_info()) else: break if commit is not None and isinstance(commit, string_types): commit = self.repo._repo.get_object(commit) self._commit = commit if commit is None: tree = Tree() else: try: tree = self.repo._repo.get_object(commit.tree) except ObjectMissing: if retry and branch is not None: if branch != 'master': del self.repo._repo.refs['refs/heads/%s' % branch] return self.checkout(branch='master', retry=False) else: six.reraise(*sys.exc_info()) self._tree = tree self._working_tree = tree.copy() self._blobs = {} # TODO: Fail if there are changes in working tree @classmethod def setup(cls): Repoman.setup(getattr(settings, 'GITSTORAGE_REPO_BACKEND', 'dulwich.repo.Repo')) def _open(self, name, mode='rb'): name = self.path(name) logger.debug('Dulwich open: {}'.format(name)) if self.isfile(name): _, sha = self._working_tree[name] if sha in self._blobs: blob = self._blobs[sha] else: blob = self.repo._repo.get_object(sha) self._blobs[sha] = blob return ContentFile(blob.data, name) raise IOError(2, 'No file or directory', name) def _save(self, name, content): name = self.path(name) blob = Blob.from_string(content.read()) self._blobs[blob.id] = blob self._working_tree.add(name, FILE_MODE, blob.id) return name def delete(self, name): name = self.path(name) if self.isfile(name): del self._working_tree[name] else: raise IOError(2, 'No file or directory', name) if name.endswith('.json'): dir_path = name[:-len('.json')] if self.isdir(dir_path): self.rmtree(dir_path) def exists(self, name): name = self.path(name) if self.isfile(name) or self.isdir(name): return True return False def listdir(self, path): path = '{}/'.format(self.path(path)) # All paths should be relative to the project directory path_parts = len(path.strip('/').split('/')) if path == '/': path = '' if path: path_parts += 1 dirs, files = set(), set() for p in self._working_tree: if not p.startswith(path): continue split = p.split('/') try: section = split[path_parts - 1] except IndexError: # File in parent directory with similar name to directory continue if len(split) == path_parts: files.add(section) else: dirs.add(section) return sorted(dirs), sorted(files) def isdir(self, name): name = self.path(name) dir_name = name + '/' if any(path.startswith(dir_name) for path in self._working_tree): return True return False def isfile(self, name): name = self.path(name) if name in self._working_tree: return True return False def move(self, old_name, new_name, allow_overwrite=False): old_name = self.path(old_name) if not self.exists(old_name): raise IOError(2, 'No file or directory', old_name) new_name = self.path(new_name) if old_name == new_name: return if self.isfile(old_name): self._working_tree[new_name] = self._working_tree[old_name] del self._working_tree[old_name] elif self.isdir(old_name): dir_name = old_name + '/' for path in self._working_tree: if path.startswith(dir_name): new_path = self.path( '{}/{}'.format(new_name, path[len(old_name):])) self._working_tree[new_path] = self._working_tree[path] del self._working_tree[path] def rmtree(self, name): name = self.path(name) if not self.isdir(name): raise IOError(2, 'No file or directory', name) dir_name = name + '/' for path, _, _ in self._working_tree.items(): if path.startswith(dir_name): del self._working_tree[path] def path(self, path): path = path.lstrip('.').strip('/') if path: path = os.path.relpath(path) # Handle paths for mysql repo where there is no project name if path.startswith(getattr(self.repo._repo, '_name', '\0')): path = os.path.join(*(path.split('/')[1:])) try: return path.encode('utf-8') except AttributeError: return path def commit(self, message='Saving multiple files'): working_tree = self._working_tree if working_tree == self._tree: return if self._commit is None: self.repo = repo = Repoman.create_repo(self.name, self.author) self._commit = repo.last_commit fake_store = { self._tree.id: self._tree, working_tree.id: working_tree, } blobs = [] for change in tree_changes(fake_store, self._tree.id, working_tree.id): if change.new.sha in self._blobs: blobs.append(self._blobs[change.new.sha]) commit = self.repo._create_commit() commit.parents = [self._commit.id] commit.tree = working_tree.id commit.message = message self.repo._update_store(commit, working_tree, *blobs) self.repo._advance_branch(self.branch, commit) self._commit = commit self._tree = working_tree self._working_tree = working_tree.copy() def changed_files(self): if self.branch == 'master': return [] try: changes = self.repo.get_branch_changed_entries(self.branch) except KeyError: return [] return [ (entry.type, entry.new.path, entry.old.path) for entry in changes ] ================================================ FILE: portia_server/storage/jsondiff.py ================================================ import difflib from collections import namedtuple from six.moves import zip_longest _BLANK = object() class Conflict(object): def __init__(self, mine, other, base): self.mine = [mine] if mine is not _BLANK else None self.other = [other] if other is not _BLANK else None self.base = [base] if base is not _BLANK else None @classmethod def from_prepared(cls, mine, other, base): m = mine[0] if mine else _BLANK o = other[0] if other else _BLANK b = base[0] if base else _BLANK conflict = cls(m, o, b) for m, o, b in zip_longest(mine[1:], other[1:], base[1:], fillvalue=_BLANK): conflict.update(m, o, b) return conflict @classmethod def resolve_sub_conflict(cls, mine, other): c = cls.from_prepared(mine, other, []) return c.resolve_conflict() or [] def update(self, m, o, b): if m is not _BLANK: self.mine.append(m) if o is not _BLANK: self.other.append(o) if b is not _BLANK: self.base.append(b) def resolve_conflict(self): if self.mine is None and self.other is not None: return self.other if self.other is None and self.mine is not None: return self.mine if self.other == self.mine: return self.mine combined = set(self.mine or []) | set(self.other or []) if (self.base is not None and not any(i in combined for i in self.base)): return [self] mine = self.mine if self.mine else [] other = self.other if self.other else [] i_mine, i_other = iter(mine), iter(other) result, new_mine, new_other = [], [], [] for diff in difflib.Differ().compare([str(i) for i in other], [str(i) for i in mine]): if ((diff.startswith('+') and (new_other or result)) or (diff.startswith('-') and (new_mine or result)) or (result and (new_other or new_mine))): if new_mine or new_other: result.insert(0, Conflict.from_prepared(new_mine, new_other, [])) result.extend(Conflict.resolve_sub_conflict( [i for i in i_mine], [i for i in i_other])) break elif diff.startswith('-'): new_other.append(next(i_other)) elif diff.startswith('+'): new_mine.append(next(i_mine)) elif diff.startswith(' '): next(i_other) result.append(next(i_mine)) return result def _asdict(self): return { 'my_op': 'CHANGED', 'my_val': self.mine, 'other_op': 'CHANGED', 'other_val': self.other, 'base_val': self.base } def __eq__(self, other): return (self.mine == other.mine and self.other == other.other and self.base == other.base) def __str__(self): return 'Conflict{}'.format(str((self.mine, self.other, self.base))) def __repr__(self): return str(self) def merge_lists(base, mine, other): if mine == other: return mine if other == base: return mine if mine == base: return other result = [] last_conflict = False for i, (m, o, b) in enumerate(zip_longest(mine, other, base, fillvalue=_BLANK)): if (m == o and _BLANK not in (m, o) or isinstance(m, dict) and isinstance(o, dict)): result.append(m) else: # Conflict if last_conflict: c = result[-1] c.update(m, o, b) else: c = Conflict(m, o, b) result.append(c) last_conflict = True continue last_conflict = False offset = 0 for i, r in enumerate(result[:]): if isinstance(r, Conflict): c = r.resolve_conflict() or [] result = result[:i + offset] + c + result[i + offset + 1:] offset += len(c) - 1 return result class JsonDiff(object): """ Compares two json objects and stores the differences. Only the outermost objects are considered, the comparison does not recurse into nested objects. """ def __init__(self, old, new): set_new, set_old = set(new), set(old) common = set_new & set_old self.added = list(set_new - common) self.removed = list(set_old - common) self.changed = [k for k in common if new[k] != old[k]] self.unchanged = [k for k in common if new[k] == old[k]] def op_for_field(self, field_name): for operation in ('ADDED', 'UNCHANGED', 'CHANGED', 'REMOVED'): if field_name in getattr(self, operation.lower()): return operation return None FieldDiff = namedtuple( 'DiffOp', ['my_op', 'my_val', 'other_op', 'other_val', 'base_val']) def merge_jsons(base, mine, other): """ Performs a 3-way merge of mine and other using base as the common ancestor. Some conflicts are automatically resolved, e.g. mine and other both delete the same field. Conflicts that can't be automatically resolved (e.g. mine and other assign different values to the same field) are serialized into the merged json in a way that can be used for a later manual resolve: field: { __CONFLICT: base_val: X, # the original value of the field my_val: Y, # the value assigned by mine json my_op: Z, # the operation performed by mine json other_val: U, # the value assigned by other json other_op: W, # the operation performed by other json } my_op and other_op can take any of this values: 'ADDED', 'REMOVED', 'CHANGED', 'UNCHAGED'. If my_op == 'DELETED' then my_value == None (the same applies to other_op and other_val respectively). The merge recurses into dictionaries but considers lists as atomic values. Returns a tuple of the form (merged, had_conflict). """ def build_merge_dict(base, mine, other): my_diff = JsonDiff(base, mine) other_diff = JsonDiff(base, other) base, mine, other = (j if isinstance(j, dict) else {} for j in (base, mine, other)) all_fields = set(base.keys()).union(mine.keys()).union(other.keys()) merge_dict = {} for k in all_fields: base_val, my_val, other_val = ( base.get(k, {}), mine.get(k), other.get(k)) if isinstance(my_val, dict) and isinstance(other_val, dict): merge_dict[k] = build_merge_dict(base_val, my_val, other_val) if isinstance(my_val, list) and isinstance(other_val, list): merge_dict[k] = merge_lists(base_val, my_val, other_val) else: merge_dict[k] = FieldDiff(base_val=base.get(k), my_val=my_val, my_op=my_diff.op_for_field(k), other_val=other_val, other_op=other_diff.op_for_field(k)) return merge_dict def eq_vals(diff): return diff.other_val == diff.my_val def conflict(diff): return {'__CONFLICT': diff._asdict()} def resolve_json(merge_dict): out_json = {} had_conflict = False for key, diff in merge_dict.items(): if isinstance(diff, dict): out_json[key], rconflict = resolve_json(diff) had_conflict = had_conflict or rconflict if isinstance(diff, list): for i, item in enumerate(diff): if isinstance(item, Conflict): if (item.mine and isinstance(item.mine[0], dict) and '__CONFLICT' in item.mine[0]): diff[i] = item.mine[0] else: diff[i] = conflict(item) had_conflict = True out_json[key] = diff elif diff.my_op in ('UNCHANGED', None): if diff.other_op != 'REMOVED': out_json[key] = diff.other_val elif diff.my_op == 'ADDED': if diff.other_op != 'ADDED' or eq_vals(diff): out_json[key] = diff.my_val else: out_json[key] = conflict(diff) had_conflict = True elif diff.my_op == 'REMOVED': if diff.other_op == 'CHANGED': out_json[key] = conflict(diff) had_conflict = True elif diff.my_op == 'CHANGED': if diff.other_op == 'UNCHANGED' or eq_vals(diff): out_json[key] = diff.my_val else: out_json[key] = conflict(diff) had_conflict = True return out_json, had_conflict return resolve_json(build_merge_dict(base, mine, other)) ================================================ FILE: portia_server/storage/projecttemplates.py ================================================ from slybot import __version__ as slybot_version _PROJECT_TEMPLATE = """\ {}\ """ _SETTINGS_TEMPLATE = """\ # Automatically created by: portia import os SPIDER_MANAGER_CLASS = 'slybot.spidermanager.SlybotSpiderManager' EXTENSIONS = { 'slybot.closespider.SlybotCloseSpider': 1 } ITEM_PIPELINES = { 'slybot.dupefilter.DupeFilterPipeline': 1, 'slybot.meta.DropMetaPipeline': 2 } SPIDER_MIDDLEWARES = { # as close as possible to spider output 'slybot.spiderlets.SpiderletsMiddleware': 999 } DOWNLOADER_MIDDLEWARES = { 'slybot.pageactions.PageActionsMiddleware': 700, 'scrapy_splash.middleware.SplashCookiesMiddleware': 723, 'slybot.splash.SlybotJsMiddleware': 725 } PLUGINS = [ 'slybot.plugins.scrapely_annotations.Annotations', 'slybot.plugins.selectors.Selectors' ] SLYDUPEFILTER_ENABLED = True SLYDROPMETA_ENABLED = False DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter' FEED_EXPORTERS = { 'csv': 'slybot.exporter.SlybotCSVItemExporter', } CSV_EXPORT_FIELDS = None PROJECT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) try: from local_slybot_settings import * except ImportError: pass try: from slybot_settings import * except ImportError: pass """ _SETUP_PY_TEMPLATE = """\ # Automatically created by: portia from setuptools import setup, find_packages setup( name='%(name)s', version='1.0', packages=find_packages(), data_files = [ ('', ['project.json', 'items.json', 'extractors.json']), ], entry_points={ 'scrapy': [ 'settings = spiders.settings' ] }, zip_safe=True, include_package_data=True, ) """ _SCRAPY_TEMPLATE = """\ # Automatically created by: portia [settings] default = spiders.settings """ _MANIFEST_TEMPLATE = """\ include project.json include extractors.json include items.json recursive-include spiders **.json recursive-include spiders **.html """ _ITEMS_TEMPLATE = """\ {} """ _EXTRACTORS_TEMPLATE = """\ {} """ _REQUIREMENTS = """\ # Automatically created by: portia slybot=={} dateparser==0.7.0 loginform>=1.2.0 page_finder scrapylib scrapy-splash scrapy-crawlera scrapy-deltafetch scrapy-dotpersistence scrapy-pagestorage """.format(slybot_version) templates = { 'PROJECT': _PROJECT_TEMPLATE, 'SETTINGS': _SETTINGS_TEMPLATE, 'SETUP': _SETUP_PY_TEMPLATE, 'SCRAPY': _SCRAPY_TEMPLATE, 'ITEMS': _ITEMS_TEMPLATE, 'EXTRACTORS': _EXTRACTORS_TEMPLATE, 'MANIFEST': _MANIFEST_TEMPLATE, 'REQUIREMENTS': _REQUIREMENTS, } ================================================ FILE: portia_server/storage/repoman.py ================================================ from __future__ import absolute_import from time import time from collections import defaultdict from json import dumps, loads from itertools import chain from scrapy.utils.misc import load_object from dulwich.errors import ObjectMissing from dulwich.objects import Blob, Tree, Commit, Tag, parse_timezone from dulwich.diff_tree import tree_changes, RenameDetector from .jsondiff import merge_jsons CHANGE_MODIFY = 'modify' CHANGE_DELETE = 'delete' CHANGE_RENAME = 'rename' DEFAULT_USER = 'defaultuser' FILE_MODE = 0o100644 sentinel = object() class Repoman(object): """An interface to interact with Git repositories. Only json files are allowed into the repository as a custom merge algorithm is used to resolve conflicts. Changes must be recorded into the repo file by file using the save_file and delete_file methods. The expected work-flow for concurrent usage of a repo is: * User A branches the repo to make his edits. * User B branches the repo to make his edits. * User A changes some files using save_file and delete_file. * User B changes some files using save_file and delete_file. * User A publishes his changes using publish_branch. * User A deletes his edit branch. * User B tries to publish using publish_branch. If the automatic merge is not able to resolve all conflicts, the publish is unsuccessful but intermediate merge files are be created containing meta-data to help resolve the pending conflicts. * User B resolves the pending conflicts. * User B publishes his changes using publish_branch. * User B deletes his edit branch. """ def __init__(self, author): """Do not instantiate directly, use create_repo or open_repo.""" self._author = (author and author.username) or DEFAULT_USER self._encoding = 'UTF-8' self._time_zone = parse_timezone('+0000')[0] self.commit = sentinel self.last_commit = None self.tree = sentinel self.last_tree = None @classmethod def setup(cls, storage_backend): cls.storage = load_object(storage_backend) @classmethod def create_repo(cls, repo_name, author=None): """Create a new repository named repo_name.""" if cls.storage.repo_exists(repo_name): raise NameError() repoman = cls(author) repoman._repo = cls.storage.init_bare(repo_name) tree = Tree() commit = repoman._create_commit() commit.tree = tree.id commit.message = 'Initialization commit' repoman.advance_branch(commit, tree, 'master') return repoman @classmethod def open_repo(cls, repo_name, author=None): """Open an existing repository.""" repoman = cls(author) repoman._repo = cls.storage.open(repo_name) repoman.name = repo_name return repoman @classmethod def repo_exists(cls, repo_name): """Return true if a repository named repo_name can be opened.""" return cls.storage.repo_exists(repo_name) @classmethod def list_repos(cls): return cls.storage.list_repos() @classmethod def delete_repo(cls, repo_name): """Delete an existing repo.""" cls.storage.delete_repo(repo_name) @property def refs(self): return self._repo.refs def create_branch(self, branch_name, at_revision=None): """Create a new branch. If no revision is specified, the branch is created from the latest commit in master. """ at_revision = at_revision or self._get_head() self.refs['refs/heads/%s' % branch_name] = at_revision def delete_branch(self, branch_name): """Delete an existing branch. Only the reference to the branch is deleted, all commits trees and blobs are left untouched. """ del self.refs['refs/heads/%s' % branch_name] def has_branch(self, branch_name): """Return true if the specified branch exists in this repo.""" return 'refs/heads/%s' % branch_name in self.refs def get_branch(self, branch_name): """Return the branch with name branch_name.""" return self.refs['refs/heads/%s' % branch_name] def save_file(self, file_path, contents, branch_name, commit_message=None): """Save a file into the repo and advances the specified branch head. If the branch does not exist yet, it will be created. """ self._perform_file_operation( branch_name, self._save_file, file_path, contents, commit_message) def save_files(self, files, branch_name, commit_message=None): """Save a multiple files and advances the specified branch head. If the branch does not exist yet, it will be created. """ files_info = {} for path, data in files.items(): if not isinstance(data, (list, tuple)): data = (data, CHANGE_MODIFY) files_info[path] = data self._perform_file_operation( branch_name, self._save_files, files_info, commit_message) def blob_for_branch(self, file_path, branch_name): """Return the blob with the contents of file_path. The returned version of the blob is the one at the branch's head. """ return self.blob(file_path, self.get_branch(branch_name)) def blob(self, file_path, revision): """Return the blob with the contents of file_path @revision.""" tree = self._get_tree(revision) _, sha = tree[file_path] return self._repo.get_object(sha) def file_contents_for_branch(self, file_path, branch_name): """Return the the contents of file_path for the given branch.""" try: return self.blob_for_branch(file_path, branch_name).as_raw_string() except KeyError: return None def list_files_for_branch(self, branch_name): """Return a list containing all file names for the given branch.""" try: revision = self.get_branch(branch_name) except KeyError: return [] return self.list_files(revision) def list_files(self, revision): """Return a list containing all file names for the given revision.""" repo = self._repo items = repo.get_object(repo.get_object(revision).tree).items() return [i.path for i in items] def publish_branch(self, branch_name, force=False, message=None, dry_run=False): """Merge a branch into master. If master@head is an ancestor of the given branch (or force=True), all branch commits are squashed into one and then master@head is advanced accordingly. If not (probably because other user published his changes), a three way merge is performed. If no unresolved merge conflicts arise, then a publish commit is created and then master@head is advanced accordingly. If there are unresolved conflicts, a resolve conflicts commit is created containing metadata intended to help to manually resolve pending conflicts, and then branch@head is advanced. Returns True if master@head was advanced and False if there are pending conflicts. """ conflicts = self._publish_branch(branch_name, force, message) if dry_run: if conflicts: return conflicts return True if conflicts: self.advance_branch(self.commit, branch=branch_name) return False else: self.advance_branch(self.commit, self.tree) return True def _publish_branch(self, branch_name, force=False, message=None): branch = self.get_branch(branch_name) head = self._get_head() if self._is_ancestor_commit(branch, head): # Squash all the branch commits and move the master head. tree = self._get_tree(branch) commit = self._create_commit() commit.parents = [head] commit.tree = tree.id commit.message = message or 'Publishing changes' self.commit = commit return False else: # We need to merge and maybe deal with conflicts. common_ancestor = self.get_branch_checkpoints(branch_name)[-1] merge_tree, conflicts = self._merge_branches( common_ancestor, branch, head, take_mine=force) commit = self._create_commit() commit.tree = merge_tree.id if conflicts: commit.parents = [branch] commit.message = 'Resolve merge conflicts' else: commit.parents = [head] commit.message = 'Publishing changes' self.commit = commit return conflicts def advance_branch(self, commit, tree=sentinel, branch='master'): """Set head of branch to supplied commit.""" if commit is not sentinel: self._update_store(commit, tree) self._advance_branch(branch, commit) self.last_commit = commit self.last_tree = tree if commit is self.commit: self.commit = sentinel if tree is self.tree: self.tree = sentinel else: raise ValueError('Can\'t advance branch without commit') def get_published_revisions(self): """Return all commit ids that correspond to a successful publishes.""" walker = self._repo.get_walker() # TODO: find a better way of marking publish commits... # maybe use tags? return [entry.commit.id for entry in walker if entry.commit.message.startswith('Publishing')] def get_branch_checkpoints(self, branch_name): """Return all commit ids for changes made within the branch.""" branch = self.get_branch(branch_name) publish_revisions = self.get_published_revisions() walker = self._repo.get_walker(include=branch) branch_checkpoints = [] for entry in walker: commit_id = entry.commit.id branch_checkpoints.append(commit_id) if commit_id in publish_revisions: break return branch_checkpoints def get_branch_changed_entries(self, branch_name): """Return the name of all changed files within the branch.""" master_tree = self._get_tree(self.get_branch('master')) branch_tree = self._get_tree(self.get_branch(branch_name)) return tree_changes( self._repo.object_store, branch_tree.id, master_tree.id) def get_branch_changed_files(self, branch_name): """Return the name of all changed files within the branch.""" changes = self.get_branch_changed_entries(branch_name) return [entry.new.path or entry.old.path for entry in changes] def add_tag(self, tag_name): commit = self._repo['refs/heads/master'] tag = Tag() tag.name = tag_name tag.message = 'Tagged %s as %s' % (commit.id, tag_name) tag.tagger = self._author tag.object = (Commit, commit.id) tag.tag_time = int(time()) tag.tag_timezone = self._time_zone self._update_store(tag) self.refs['refs/tags/%s' % tag_name] = tag.id def checkout_tag(self, tag_name, remove=False): if ('refs/tags/%s' % tag_name) not in self.refs: raise ValueError('No tag "{}" found'.format(tag_name)) tag_ref = self.refs['refs/tags/%s' % tag_name] tag = self._repo[tag_ref] self._advance_branch( 'master', self._repo.object_store.get_object(tag.object[1])) if remove: del self.refs['refs/tags/%s' % tag_name] def _merge_branches(self, base, mine, other, take_mine=False): def load_raw(path, branch): try: blob = self.blob(path, branch) except (KeyError, TypeError): return '{}' else: return blob.as_raw_string() def load_json(path, branch): return loads(load_raw(path, branch)) merge_tree = Tree() base_tree, my_tree, other_tree = (self._get_tree(x) for x in (base, mine, other)) ren_detector = RenameDetector(self._repo.object_store) conflicts = {} my_changes, other_changes = ( tree_changes( self._repo.object_store, base_tree.id, x.id, want_unchanged=True, rename_detector=ren_detector) for x in (my_tree, other_tree)) changes_by_path = defaultdict(list) for change in chain(my_changes, other_changes): if change.type == CHANGE_DELETE or change.type == CHANGE_RENAME: path = change.old.path else: path = change.new.path changes_by_path[path].append(change) had_conflict = False for path, changes in changes_by_path.items(): if len(changes) == 2: my_changes, other_changes = changes if my_changes.type == CHANGE_DELETE: if other_changes.type in (CHANGE_RENAME, CHANGE_MODIFY): merge_tree.add(other_changes.new.path, FILE_MODE, other_changes.new.sha) else: continue elif other_changes.type == CHANGE_DELETE: if my_changes.type in (CHANGE_RENAME, CHANGE_MODIFY): merge_tree.add(my_changes.new.path, FILE_MODE, my_changes.new.sha) else: continue else: try: jsons = [load_json(path, x) for x in (base, mine, other)] except ValueError: # Handle non json data blob = Blob.from_string(load_raw(path, mine)) self._update_store(blob) merge_tree.add(path, FILE_MODE, blob.id) continue base_json, my_json, other_json = jsons # When dealing with renames, file contents are under the # 'new' path. Note that the file will be finally stored # under the name given by the last rename. if other_changes.type == CHANGE_RENAME: other_json = load_json(other_changes.new.path, other) path = other_changes.new.path if my_changes.type == CHANGE_RENAME: my_json = load_json(my_changes.new.path, mine) path = my_changes.new.path if take_mine: merged_json = my_json or other_json or base_json else: merged_json, merge_conflict = merge_jsons(*jsons) if merge_conflict: conflicts[path] = merged_json had_conflict = had_conflict or merge_conflict merged_blob = Blob.from_string( dumps(merged_json, sort_keys=True, indent=4)) self._update_store(merged_blob) merge_tree.add(path, FILE_MODE, merged_blob.id) else: try: data = (load_json(path, mine) or load_json(path, other) or load_json(path, base)) except ValueError: # Loading a non json file blob = Blob.from_string(load_raw(path, mine)) else: blob = Blob.from_string(dumps(data, sort_keys=True, indent=4)) self._update_store(blob) merge_tree.add(path, FILE_MODE, blob.id) self._update_store(merge_tree) return merge_tree, conflicts def _perform_file_operation(self, branch_name, operation, *args): if not self.has_branch(branch_name): self.create_branch(branch_name) parent_commit = self.get_branch(branch_name) commit = operation(parent_commit, *args) self._advance_branch(branch_name, commit) def _save_file(self, parent_commit, file_path, contents, commit_message): commit_message = commit_message or 'Saving %s' % file_path return self._save_files( parent_commit, {file_path: (contents, CHANGE_MODIFY)}, commit_message) def _save_files(self, parent_commit, files, commit_message): tree = self._get_tree(parent_commit) blobs = [] for file_path, (contents, change) in files.items(): if change == CHANGE_DELETE: try: del tree[file_path] except KeyError: pass else: blob = Blob.from_string(contents) tree.add(file_path, FILE_MODE, blob.id) blobs.append(blob) commit = self._create_commit() commit.parents = [parent_commit] commit.tree = tree.id commit.message = commit_message or 'Saving multiple files' self._update_store(commit, tree, *blobs) return commit def _update_store(self, *args): objects = [(obj, None) for obj in args if obj not in (None, sentinel)] self._repo.object_store.add_objects(objects) def _advance_branch(self, branch_name, commit): self.refs['refs/heads/%s' % branch_name] = commit.id def _get_tree(self, revision): repo = self._repo return repo.get_object(repo.get_object(revision).tree) def _create_commit(self): commit = Commit() commit.author = commit.committer = self._author commit.commit_time = commit.author_time = int(time()) commit.commit_timezone = commit.author_timezone = self._time_zone commit.encoding = self._encoding return commit def _get_head(self): try: return self._repo.head() except KeyError: return None def _is_ancestor_commit(self, descendant, ancestor): walker = self._repo.get_walker(include=descendant) try: for entry in walker: if entry.commit.id == ancestor: return True except ObjectMissing: return True return False ================================================ FILE: portiaui/.bowerrc ================================================ { "directory": "bower_components", "analytics": false } ================================================ FILE: portiaui/.editorconfig ================================================ # EditorConfig helps developers define and maintain consistent # coding styles between different editors and IDEs # editorconfig.org root = true [*] end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true indent_style = space indent_size = 4 [*.js] indent_style = space indent_size = 4 [*.hbs] indent_style = space indent_size = 4 [*.css] indent_style = space indent_size = 4 [*.html] indent_style = space indent_size = 4 [*.{diff,md}] trim_trailing_whitespace = false ================================================ FILE: portiaui/.ember-cli ================================================ { "disableAnalytics": true } ================================================ FILE: portiaui/.gitignore ================================================ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /tmp # dependencies /node_modules /bower_components # misc /.sass-cache /connect.lock /coverage/* /libpeerconnection.log npm-debug.log testem.log ================================================ FILE: portiaui/.jshintrc ================================================ { "predef": [ "document", "window", "$", "cookie", "moment", "URI", "TreeMirror", "-Promise", "Raven", "Modernizr" ], "browser": true, "boss": true, "curly": true, "debug": false, "devel": true, "eqeqeq": true, "evil": true, "forin": false, "immed": false, "indent": 4, "laxbreak": false, "maxlen": 100, "newcap": true, "noarg": true, "noempty": false, "nonew": false, "nomen": false, "onevar": false, "plusplus": false, "regexp": false, "undef": true, "sub": true, "strict": false, "white": false, "eqnull": true, "esnext": true, "unused": true } ================================================ FILE: portiaui/.watchmanconfig ================================================ { "ignore_dirs": ["tmp", "dist"] } ================================================ FILE: portiaui/app/adapters/application.js ================================================ import Ember from "ember"; import DS from "ember-data"; import UrlTemplates from "ember-data-url-templates"; const { inject: { service } } = Ember; const DELETED_EXTENSION = 'https://portia.scrapinghub.com/jsonapi/extensions/deleted'; const UPDATES_EXTENSION = 'https://portia.scrapinghub.com/jsonapi/extensions/updates'; function filter_update_errors(errors, pointer) { return errors.filter(data => !data.source || !data.source.pointer || data.source.pointer.startsWith(pointer) ).map(data => { if (!data.source || !data.source.pointer) { return data; } return Ember.assign({}, data, { source: { pointer: data.source.pointer.slice(pointer.length - 1) } }); }); } export default DS.JSONAPIAdapter.extend(UrlTemplates, { changes: service(), savingNotification: service(), loadingSlider: service(), uiState: service(), findRecordUrlTemplate: '{+host}{+selfLink}', createRecordUrlTemplate: '{+host}{+relatedLink}', updateRecordUrlTemplate: '{+host}{+selfLink}', deleteRecordUrlTemplate: '{+host}{+selfLink}', urlSegments: { selfLink(type, id, snapshot /*, query */) { // return the self link returned by a previous response, when the // record was included in a relationship request or a json api // compound document. return snapshot._internalModel._links.self; }, relatedLink(type, id, snapshot /*, query */) { // find a one to many relationship to the record and use it's // related link. const relationships = []; snapshot.eachRelationship((name, relationship) => { relationships.push([name, relationship]); }); for (let [name, relationship] of relationships) { if (relationship.kind !== 'belongsTo') { continue; } const relatedSnapshot = snapshot.belongsTo(name); if (!relatedSnapshot) { continue; } const relatedRecord = relatedSnapshot._internalModel; const inverseRelationship = snapshot.record.inverseFor(name); if (inverseRelationship.kind !== 'hasMany') { continue; } const inverseName = inverseRelationship.name; const manyRelationship = relatedRecord._relationships.get(inverseName); if (manyRelationship.link) { return manyRelationship.link.split('?', 1)[0]; } } } }, createRecord(store, type, snapshot) { // TODO: remove when ds-improved-ajax feature is enabled const request = this._requestFor({ store, type, snapshot, requestType: 'createRecord' }); return this._makeRequest(request); }, updateRecord(store, type, snapshot) { // TODO: remove when ds-improved-ajax feature is enabled const request = this._requestFor({ store, type, snapshot, requestType: 'updateRecord' }); return this._makeRequest(request); }, deleteRecord(store, type, snapshot) { // TODO: remove when ds-improved-ajax feature is enabled const request = this._requestFor({ store, type, snapshot, requestType: 'deleteRecord' }); return this._makeRequest(request); }, dataForRequest(params) { // TODO: use _super when ds-improved-ajax feature is enabled let {store, type, snapshot, requestType} = params; type = type || (snapshot && snapshot.type); const serializer = store.serializerFor(type.modelName); let data = {}; switch (requestType) { case 'createRecord': serializer.serializeIntoHash(data, type, snapshot, { includeId: true }); break; case 'updateRecord': // allow partial updates by specifying adapterOptions.partial serializer.serializeIntoHash(data, type, snapshot, { includeId: true, partial: snapshot.adapterOptions && snapshot.adapterOptions.partial }); break; case 'deleteRecord': data = undefined; break; default: data = this._super(...arguments); break; } // merge data from sub-requests for updates extension if (requestType === 'createRecord' || requestType === 'updateRecord' || requestType === 'deleteRecord') { const coalesce = snapshot.adapterOptions && snapshot.adapterOptions.coalesce; if (coalesce && coalesce.type === 'main') { const coalesced = []; if (coalesce.updates) { for (let {data} of coalesce.updates) { coalesced.push(data.data); } } data = Ember.assign(data || {}, { links: { profile: [UPDATES_EXTENSION] }, aliases: { updates: UPDATES_EXTENSION }, meta: { updates: coalesced } }); } } return data; }, methodForRequest(params) { // TODO: remove when ds-improved-ajax feature is enabled switch (params.requestType) { case 'createRecord': return 'POST'; case 'updateRecord': return 'PATCH'; case 'deleteRecord': return 'DELETE'; } return 'GET'; }, urlForRequest(params) { // TODO: remove when ds-improved-ajax feature is enabled let {type, id, snapshot, requestType} = params; type = type || (snapshot && snapshot.type); id = id || (snapshot && snapshot.id); if (requestType === 'createRecord' || requestType === 'updateRecord' || requestType === 'deleteRecord') { return this.buildURL(type.modelName, id, snapshot, requestType); } return this._super(...arguments); }, headersForRequest(params) { const headers = this.get('headers') || {}; const profiles = []; const acceptProfiles = [DELETED_EXTENSION]; if (params.snapshot.adapterOptions && params.snapshot.adapterOptions.coalesce) { profiles.push(UPDATES_EXTENSION); acceptProfiles.push(UPDATES_EXTENSION); } if (profiles.length) { headers['Content-Type'] = `application/vnd.api+json; profile="${profiles.join(' ')}"`; } else { headers['Content-Type'] = 'application/vnd.api+json'; } if (acceptProfiles.length) { headers['Accept'] = `application/vnd.api+json; profile="${acceptProfiles.join(' ')}"`; } else { headers['Accept'] = 'application/vnd.api+json'; } return headers; }, _requestFor(params) { // TODO: use _super when ds-improved-ajax feature is enabled const method = this.methodForRequest(params); const url = this.urlForRequest(params); const headers = this.headersForRequest(params); const data = this.dataForRequest(params); const request = { method, url, headers, data }; return Ember.assign(request, { store: params.store, type: params.type, snapshot: params.snapshot, requestType: params.requestType }); }, _makeRequest(request) { // TODO: use _super instead of this.ajax when ds-improved-ajax feature is enabled const {requestType} = request; if (requestType === 'createRecord' || requestType === 'updateRecord' || requestType === 'deleteRecord') { const {method, url, data, store, type, snapshot} = request; let promise; const coalesce = snapshot.adapterOptions && snapshot.adapterOptions.coalesce; if (coalesce) { const {type: coalesceType, updates} = coalesce; if (coalesceType === 'main') { // the main request of the bulk operation, resolve the promises // for the included models when this promise resolves promise = this.ajax(url, method, request); promise.then(response => { const serializer = store.serializerFor(type.modelName); const requests = {}; const responses = {}; for (let {type, snapshot} of updates) { const modelName = type.modelName; const id = snapshot.id; const type_requests = requests[modelName] || ( requests[modelName] = {}); type_requests[id] = true; } let aliases = this._getExtentionAliases(response, UPDATES_EXTENSION); if (aliases.length && response.meta) { for (let alias of aliases) { for (let update of response.meta[alias]) { const normalized = serializer._normalizeResourceHelper(update); const {type, id} = normalized; if (!requests[type] || !requests[type][id]) { const error = new DS.AdapterError([{ title: "Unexpected update confirmation", detail: `${response}` }], "JSON API updates response contained " + "confirmations for resources that were not " + "requested."); for (let {resolver} of updates) { resolver.reject(error); } throw error; } const type_responses = responses[type] || ( responses[type] = {}); type_responses[id] = update; } } } // treat deleted as update confirmations aliases = this._getExtentionAliases(response, DELETED_EXTENSION); if (aliases.length && response.meta) { for (let alias of aliases) { for (let deleted of response.meta[alias]) { const normalized = serializer._normalizeResourceHelper(deleted); const {type, id} = normalized; if (requests[type] && requests[type][id]) { const type_responses = responses[type] || ( responses[type] = {}); type_responses[id] = deleted; } } } } if (response.included) { const filtered_included = []; for (let included of response.included) { const normalized = serializer._normalizeResourceHelper(included); const {type, id} = normalized; if (responses[type]) { if (responses[type][id]) { responses[type][id] = included; } } else { filtered_included.push(included); } } response.included = filtered_included; } for (let {type, snapshot, resolver} of updates) { const modelName = type.modelName; const id = snapshot.id; if (responses[modelName] && responses[modelName][id]) { resolver.resolve({ data: responses[modelName][id] }); continue; } resolver.reject(new DS.AdapterError([{ title: "Missing update confirmation", detail: `${response}` }], "JSON API updates response was missing confirmation for " + "an updated resource")); } return response; }, error => { for (let i = 0; i < updates.length; i++) { const {resolver} = updates[i]; const pointer = `/meta/updates/${i}/`; const modelError = new error.constructor( filter_update_errors(error.errors, pointer), error.message); resolver.reject(modelError); } }); } else { // a sub-request of the bulk operation, return a promise that // will be resolved when the main request completes. const resolver = Ember.RSVP.defer(); updates.push({ type, snapshot, data, resolver }); return resolver.promise; } } else { promise = this.ajax(url, method, request); } // handle our custom json api extension for listing records that were // deleted in the backend and should be unloaded. promise.then(response => { const aliases = this._getExtentionAliases(response, DELETED_EXTENSION); if (aliases.length && response.meta) { const serializer = store.serializerFor(type.modelName); for (let alias of aliases) { for (let deleted of response.meta[alias]) { const normalized = serializer._normalizeResourceHelper(deleted); if (!normalized) { continue; } const record = store.peekRecord(normalized.type, normalized.id); if (record) { if (record.get('isSaving')) { record.one('didCommit', record.unloadRecord); } else { record.unloadRecord(); } } } } } return response; }); // update saving status this.get('savingNotification').start(); this.get('loadingSlider').startLoading(); promise.finally(() => { const project = this.get('uiState.models.project'); if (project) { this.set('changes.hasChanges', true); } this.get('savingNotification').end(); this.get('loadingSlider').endLoading(); }); return promise; } return this.ajax(request.url, request.method, request); }, _getExtentionAliases(response, extention) { const aliases = []; if (response && response.links && response.links.profile && response.links.profile.includes(extention)) { for (let alias of Object.keys(response.aliases)) { if (response.aliases[alias] === extention) { aliases.push(alias); } } } return aliases; }, ajaxOptions(url, method, request = {}) { // TODO: move to _requestToJQueryAjaxHash when ds-improved-ajax feature is enabled const {headers} = request; const options = Ember.assign({}, request); delete options.method; delete options.url; delete options.headers; const hash = this._super(url, method, options); if (headers) { hash.contentType = headers['Content-Type']; delete headers['Content-Type']; hash.beforeSend = function(xhr) { Object.keys(headers).forEach((key) => xhr.setRequestHeader(key, headers[key])); }; } return hash; } }); ================================================ FILE: portiaui/app/adapters/project.js ================================================ import ApplicationAdapter from './application'; export default ApplicationAdapter.extend({ urlTemplate: '{+host}/api/projects{/id}', findRecordUrlTemplate: '{+host}/api/projects{/id}', createRecordUrlTemplate: '{+host}/api/projects', shouldReloadRecord() { return true; } }); ================================================ FILE: portiaui/app/app.js ================================================ import Ember from 'ember'; import Resolver from './resolver'; import loadInitializers from 'ember-load-initializers'; import config from './config/environment'; let App; Ember.MODEL_FACTORY_INJECTIONS = true; App = Ember.Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, Resolver, customEvents: { transitionend: 'transitionEnd' } }); loadInitializers(App, config.modulePrefix); export default App; ================================================ FILE: portiaui/app/components/.gitkeep ================================================ ================================================ FILE: portiaui/app/components/add-start-url-button.js ================================================ import Ember from 'ember'; const { computed, inject: { service } } = Ember; export default Ember.Component.extend({ tagName: '', browser: service(), dispatcher: service(), url: computed.readOnly('browser.url'), emptyUrl: computed.not('url'), disableStartUrl: computed.or('emptyUrl', 'browser.invalidUrl'), newStartUrl: computed('url', 'spider.startUrls.[]', function() { const url = this.get('url'); const startUrls = this.get('spider.startUrls').mapBy('url'); return url && !startUrls.includes(url); }), actions: { toggleStartUrl() { if (this.get('emptyUrl')) { return; } this._toggleStartUrl(); } }, _toggleStartUrl() { if (this.get('newStartUrl')) { this.get('dispatcher').addStartUrl(this.get('spider'), this.get('url')); } else { this.get('dispatcher').removeStartUrl(this.get('spider'), this.get('_startUrl')); } }, _startUrl: computed('spider.startUrls.[]', 'url', function() { return this.get('spider.startUrls') .findBy('url', this.get('url')); }) }); ================================================ FILE: portiaui/app/components/animation-container.js ================================================ import Ember from 'ember'; import { attrValue } from '../utils/attrs'; export default Ember.Component.extend({ positionMonitor: Ember.inject.service(), classNames: ['animation-container'], classNameBindings: ['fade', 'hidden'], fade: false, hidden: false, setHeight: true, setWidth: true, didReceiveAttrs({oldAttrs, newAttrs}) { if (attrValue(newAttrs.hide)) { if (!oldAttrs) { this.setProperties({ fade: true, hidden: true }); } else if (!attrValue(oldAttrs.hide)) { // if hide is toggled quickly enough, and the opacity hasn't yet changed, then the // transitionend event will not fire to set hidden = true. if ((+this.$().css('opacity') === 0)) { this.setProperties({ fade: true, hidden: true }); } else { this.set('fade', true); } } } else { if (!oldAttrs) { this.setProperties({ fade: true, hidden: true }); Ember.run.later(() => { this.set('hidden', false); Ember.run.later(this, this.set, 'fade', false, 50); }, 50); } else if (attrValue(oldAttrs.hide)) { this.set('hidden', false); Ember.run.later(this, this.set, 'fade', false, 50); } } }, didInsertElement() { const positionMonitor = this.get('positionMonitor'); Ember.run.schedule('afterRender', () => { this.content = this.element.children[0]; positionMonitor.registerElement( this.element, this, this.readPosition, this.updatePosition); positionMonitor.registerElement( this.content, this, null, this.updateSize); Ember.run.scheduleOnce('afterRender', positionMonitor, positionMonitor.update); }); }, willDestroyElement() { const positionMonitor = this.get('positionMonitor'); positionMonitor.unRegisterElement( this.element, this, this.readPosition, this.updatePosition); positionMonitor.unRegisterElement( this.content, this, null, this.updateSize); }, readPosition(rects, boundingRect, element) { this.containerPosition = Ember.$(element).position(); }, updatePosition(rects, boundingRect) { const content = this.content; let style = ''; if (boundingRect.top || boundingRect.bottom || boundingRect.left || boundingRect.right) { const left = Math.round(this.containerPosition.left); const top = Math.round(this.containerPosition.top); style = `transform: translate(${left}px, ${top}px);`; } content.setAttribute('style', style); }, updateSize(rects, boundingRect) { const width = Math.round(boundingRect.width); const height = Math.round(boundingRect.height); let style = ''; if (this.get('setWidth')) { style += `width: ${width}px;`; } if (this.get('setHeight')) { style += `height: ${height}px;`; } this.element.setAttribute('style', style); }, transitionEnd($event) { if ($event.originalEvent.propertyName === 'opacity' && $event.originalEvent.target === this.element) { if (this.get('fade')) { this.set('hidden', true); } } } }); ================================================ FILE: portiaui/app/components/annotation-options.js ================================================ import Ember from 'ember'; import { getAttributeList, hasContentAttribute } from './inspector-panel'; export default Ember.Component.extend({ uiState: Ember.inject.service(), dispatcher: Ember.inject.service(), tagName: '', annotation: null, invalidSelector: false, selectionModeOptions: [ { value: 'auto', label: 'Automatic' }, { value: 'css', label: 'CSS selector' }, { value: 'xpath', label: 'XPath selector' } ], attribute: Ember.computed('annotation.attribute', 'attributes.[]', { get() { return this.get('attributes').findBy('attribute', this.get('annotation.attribute')); }, set(key, value) { this.set('annotation.attribute', value.attribute); return value; } }), text_content: Ember.computed('uiState.viewPort.selectedElement', function() { let hasContent = hasContentAttribute(this.get('uiState.viewPort.selectedElement')); return hasContent ? 'text-content' : 'content'; }), attributes: Ember.computed('uiState.viewPort.selectedElement', function() { return getAttributeList(this.get('uiState.viewPort.selectedElement')); }), selectionMode: Ember.computed('annotation.selectionMode', { get() { return this.selectionModeOptions.findBy('value', this.get('annotation.selectionMode')); }, set(key, value) { this.set('annotation.selectionMode', value.value); return value; } }), cssSelector: Ember.computed({ get() { return this.get('annotation.selector'); }, set(key, value) { if (this.get('invalidSelector')) { return this.get('cssSelector'); } else { const annotation = this.get('annotation'); this.setAnnotationSelector(annotation, value); return value; } } }), editedCssSelector: Ember.computed({ get() { return null; }, set(key, value) { const annotation = this.get('annotation'); if (value === null) { this.set('invalidSelector', false); this.setAnnotationSelector(annotation, this.get('cssSelector')); } else { let invalidSelector = false; try { document.querySelectorAll(value); } catch (e) { invalidSelector = true; } this.set('invalidSelector', invalidSelector); if (!invalidSelector) { this.setAnnotationSelector(annotation, value); } } return value; } }), updateCssSelector: Ember.observer('annotation.selector', function() { if (this.get('editedCssSelector') === null) { this.set('cssSelector', this.get('annotation.selector')); } }), setAnnotationSelector(annotation, selector) { return annotation.get('parent.sample').then(sample => { annotation.setSelector(selector); return this.updateSelector(sample); }); }, updateSelector(sample) { if (!this._updateSelectorPromise) { this._updateSelectorPromise = this._updateSelector(sample); } else if (!this._updateSelectorPromise.pending) { this._updateSelectorPromise.pending = true; this._updateSelectorPromise.then(() => { return (this._updateSelectorPromise = this._updateSelector(sample)); }); } return this._updateSelectorPromise; }, _updateSelector(sample) { const dispatcher = this.get('dispatcher'); const promise = dispatcher.updateSampleSelectors(sample).then(() => { if (this._updateSelectorPromise === promise) { delete this._updateSelectorPromise; } }); return promise; }, actions: { save() { this.set('annotation.text_content', this.get('text_content')); const promise = this.get('annotation').save(); return this._updateSelectorPromise ? this._updateSelectorPromise.then(() => promise) : promise; } } }); ================================================ FILE: portiaui/app/components/browser-iframe.js ================================================ import Ember from 'ember'; import { storageFor } from 'ember-local-storage'; import { cleanUrl, shortGuid } from '../utils/utils'; import interactionEvent from '../utils/interaction-event'; import treeMirrorDelegate from '../utils/tree-mirror-delegate'; import { NAVIGATION_MODE } from '../services/browser'; function hashString(string) { let hash = 5381; for (let c of string) { hash = ((hash << 5) + hash) + c.charCodeAt(0); } if (hash < 0) { hash += 0xFFFFFFFF + 1; } return hash.toString(16); } const BrowserIFrame = Ember.Component.extend({ browser: Ember.inject.service(), overlays: Ember.inject.service(), webSocket: Ember.inject.service(), uiState: Ember.inject.service(), cookiesStore: storageFor('cookies'), pageLoadStore: storageFor('page-loads'), extractedItems: Ember.inject.service(), tagName: 'iframe', classNames: ['browser-iframe'], classNameBindings: ['overlays.hasOverlays:has-overlays'], splashUrl: null, disabled: Ember.computed.alias('browser.disabled'), document: Ember.computed.alias('browser.document'), loading: Ember.computed.alias('browser.loading'), url: Ember.computed.readOnly('browser.url'), baseurl: Ember.computed.readOnly('browser.baseurl'), spider: Ember.computed.readOnly('uiState.models.spider.id'), project: Ember.computed.readOnly('uiState.models.project.id'), init() { this._super(); this.loadCookies(); this.frameEventListeners = []; }, click() { if (this.attrs.clickHandler) { /* For some reason, when using Ember.run, if the handler initiates a route transition and the page in the iframe has a tag, the url is changed to the route uri concatenated to the iframe's url. Using Ember.run.next fixes this. */ Ember.run.next(this, this.attrs.clickHandler, ...arguments); } }, willInsertElement() { if (BrowserIFrame.instances) { throw new Error('The can be only one browser-iframe instance!'); } BrowserIFrame.instances++; const ws = this.get('webSocket'); ws.connect(); ws.addCommand('loadStarted', this, this.msgLoadStarted); ws.addCommand('loadFinished', this, this.msgLoadFinished); ws.addCommand('metadata', this, this.msgMetadata); ws.addCommand('load', this, this.msgLoad); ws.addCommand('cookies', this, this.msgCookies); ws.addCommand('mutation', this, this.msgMutation); ws.addCommand('save_html', this, this.noop); }, didInsertElement() { Ember.run.schedule('afterRender', () => { this.setProperties({ disabled: false, document: null }); this.loadUrl(); }); }, willDestroyElement() { const ws = this.get('webSocket'); ws.removeCommand('loadStarted', this, this.msgLoadStarted); ws.removeCommand('loadFinished', this, this.msgLoadFinished); ws.removeCommand('metadata', this, this.msgMetadata); ws.removeCommand('load', this, this.msgLoad); ws.removeCommand('cookies', this, this.msgCookies); ws.removeCommand('mutation', this, this.msgMutation); ws.removeCommand('save_html', this, this.noop); ws.close(); this.setProperties({ disabled: true, document: null }); BrowserIFrame.instances--; }, documentLoaded() { this.set('document', this.element.contentDocument); }, /** * Loads and displays a url interactively * Can only be called in "browse" mode. */ loadUrl: Ember.observer('url', 'baseurl', 'webSocket.closed', function() { Ember.run.scheduleOnce('sync', this, this._loadUrl); }), _loadUrl() { const url = this.get('url'); let baseurl = this.get('baseurl'); if (!url || !url.includes('://') || !cleanUrl(url)) { return; } if (this.get('webSocket.closed')) { this.splashUrl = null; if (this.get('lastLoadPromise')) { this.set('lastLoadData', null); Ember.run.cancel(this.get('lastLoadPromise')); this.failedLoad(navigator.onLine ? 'server_disconnect' : 'user_disconnect'); } return; } if (this.splashUrl === url) { return; } let failures = this.get(`pageLoadStore.${hashString(url)}`); if (failures && ((new Date() - new Date(failures.dt))/(1000*3600) < 1)) { let failed = failures.failed; if (failed > 3 && window.navigator.onLine) { // Tell user that page is not working with Portia this.set('webSocket.reconnectComponent', 'browser-url-blocked'); this.set('loading', false); throw new Error(`URL Blocked: ${url} in ${this.get('uiState.project.id')}`, 'websocket-browser-load'); } else if (failed > 2) { if (!this.get('webSocket.reconnectComponent')) { // Allow reload through // Allow user to manually reload page after 2 failures this.set('webSocket.reconnectComponent', 'browser-url-failing'); this.set('loading', false); throw new Error(`URL Failing: ${url} in ${this.get('uiState.project.id')}`, 'websocket-browser-load'); } } // Allow auto reload to happen two times } this.set('webSocket.reconnectComponent', null); this.visit(url, baseurl); }, visit(url, baseurl) { this.set('loading', true); this.get('webSocket').send({ _meta: { viewport: this.iframeSize(), user_agent: navigator.userAgent, cookies: this.loadCookies(), project: this.get('project'), spider: this.get('spider'), }, _command: 'load', url: url, baseurl: baseurl, }); }, msgLoadStarted(data) { this.set('loading', true); if (data.id) { this.set('lastLoadData', { id: data.id, url: data.url, }); this.set('lastLoadPromise', Ember.run.later(this, this.failedLoad, 60000)); } }, failedLoad(reason) { let url = this.get('url'); if (!url) { return; } let hash = hashString(url); let now = new Date(); let data = this.get(`pageLoadStore.${hash}`); if (data && (now - new Date(data.dt))/(1000*3600) < 1) { data.failed = data.failed + 1; } else { data = { failed: 0, reason: [] }; } data.dt = now.toISOString(); data.url = url; data.reason.push(reason || 'slow'); this.set(`pageLoadStore.${hash}`, data); }, msgLoadFinished(data) { Ember.run.cancel(this.get('lastLoadPromise')); this.set('lastLoadData', null); let hash = hashString(this.get('url')); let failures = this.get(`pageLoadStore.${hash}`); if (failures) { this.set(`pageLoadStore.${hash}`, null); } this.msgMetadata(data); }, msgLoad(data) { this.msgMetadata(data); }, msgMetadata(data) { if (data.loaded) { this.set('loading', false); } if (data.url) { this.splashUrl = data.url; this.set('browser.url', data.url); } if (data.error) { this.handleMetadataError(); } }, handleMetadataError() { this.set('loading', false); this.set('splashUrl', null); this.get('extractedItems').failExtraction('Failed Loading Page'); this.get('browser').invalidateUrl(); this.get('webSocket').send({ _meta: { spider: this.get('spider'), project: this.get('project') }, _command: 'interact' }); }, msgMutation(data) { var [action, ...args] = data._data; if(action === 'initialize') { this.iframePromise = this.clearIframe().then(() => { var doc = this.element.contentDocument; this.treeMirror = new TreeMirror(doc, treeMirrorDelegate(this)); }); } this.iframePromise.then(() => { const browser = this.get('browser'); this.treeMirror.delegate.cssEnabled = browser.get('cssEnabled'); this.treeMirror[action].apply(this.treeMirror, args); browser.trigger('contentChanged'); }); }, cookieId: Ember.computed('spider', 'project', function() { if (this.get('project') && this.get('spider')) { return `cookies:${this.get('project')}/${this.get('spider')}`.replace(/\./g, '_'); } }), msgCookies(data) { let cookies = data.cookies, cookieId = this.get('cookieId'); if (cookies && cookies.length) { this.set(`cookiesStore.${cookieId}`, cookies); } }, noop() { return null; }, loadCookies(){ let cookieId = this.get('cookieId'); if(cookieId){ let cookies = this.get(`cookiesStore.${cookieId}`); if (cookies) { return cookies; } } return {}; }, unbindEventHandlers() { $(this.element.contentDocument).off('.portia-iframe'); this.frameEventListeners.forEach(([target, event, fn, useCapture]) => { target.removeEventListener(event, fn, useCapture); }); this.frameEventListeners = []; }, addFrameEventListener(event, fn, useCapture=false) { let frameDoc = this.element.contentDocument; frameDoc.addEventListener(event, fn, useCapture); this.frameEventListeners.push([frameDoc, event, fn, useCapture]); }, bindEventHandlers() { this.unbindEventHandlers(); var $iframe = $(this.element.contentDocument); $iframe.on( ['keyup', 'keydown', 'keypress', 'input', 'mousedown', 'mouseup'].map( eventName => `${eventName}.portia.portia-iframe`).join(' '), e => { if (this.get('browser.mode') === NAVIGATION_MODE) { this.postEvent(e); } }); $iframe.on('click.portia.portia-iframe', e => { if (this.get('browser.mode') === NAVIGATION_MODE) { this.clickHandlerBrowse(e); } else { this.click(); return false; } }); this.addFrameEventListener('focus', this.postEvent.bind(this), true); this.addFrameEventListener('blur', this.postEvent.bind(this), true); this.addFrameEventListener('change', this.postEvent.bind(this), true); this.addFrameEventListener('scroll', e => Ember.run.throttle(this, this.postEvent, e, 200), true); }, clickHandlerBrowse(evt) { if (evt.which <= 1 && !evt.ctrlKey) { // Ignore right/middle click or Ctrl+click if(evt.target.tagName !== 'INPUT') { evt.preventDefault(); } this.postEvent(evt); } }, postEvent(evt) { this.get('webSocket').send({ _meta: { spider: this.get('spider'), project: this.get('project') }, _command: 'interact', interaction: interactionEvent(evt) }); }, clearIframe() { let defer = new Ember.RSVP.defer(); let iframe = this.element; let id = shortGuid(); let that = this; // Using a empty static page because using srcdoc or an data:uri gives // permission problems and/or broken baseURI behaviour in different browsers. iframe.setAttribute('src', '/static/empty-frame.html?' + id); iframe.removeAttribute('srcdoc'); // Using a message to workaround onload bug on some browsers (cough IE cough). let $win = $(window).bind('message', function onMessage(e){ if(e.originalEvent.data.frameReady === id){ that.bindEventHandlers(); Ember.run(that, that.documentLoaded); $win.unbind('message', onMessage); defer.resolve(); } }); return defer.promise; }, iframeSize() { const iframe = Ember.$(this.element); const height = Math.max(iframe.innerHeight(), 10); if (iframe) { return iframe.innerWidth() + 'x' + height; } return null; } }); BrowserIFrame.reopenClass({ instances: 0 }); export default BrowserIFrame; ================================================ FILE: portiaui/app/components/browser-url-blocked.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'span', }); ================================================ FILE: portiaui/app/components/browser-url-failing.js ================================================ import Ember from 'ember'; const { inject: { service } } = Ember; export default Ember.Component.extend({ tagName: 'span', browser: service(), actions: { reloadPage() { this.get('browser').reload(); } } }); ================================================ FILE: portiaui/app/components/browser-view-port.js ================================================ import Ember from 'ember'; import {getAttributeList} from './inspector-panel'; export default Ember.Component.extend({ browser: Ember.inject.service(), selectorMatcher: Ember.inject.service(), uiState: Ember.inject.service(), webSocket: Ember.inject.service(), classNames: ['browser-view-port', 'panel', 'panel-default'], hoverSelector: ':hover:not(html):not(body):not(head)', willInsertElement() { this.get('selectorMatcher').register(this.hoverSelector, this, this.updateHoveredElement); }, willDestroyElement() { this.get('selectorMatcher').unRegister(this.hoverSelector, this, this.updateHoveredElement); }, updateHoveredElement(elements) { const element = elements.get('lastObject'); this.set('uiState.viewPort.hoveredElement', getAttributeList(element).length ? element : null); }, actions: { viewPortClick() { if (this.attrs.clickHandler) { this.attrs.clickHandler(...arguments); } }, reconnectWebsocket() { this.get('webSocket').connect(); } } }); ================================================ FILE: portiaui/app/components/buffered-input.js ================================================ import Ember from 'ember'; import { ensurePromise } from '../utils/promises'; export default Ember.Component.extend({ tagName: '', autofocus: false, autoSelect: false, focused: false, spellcheck: true, type: 'text', value: null, viewValue: null, didInsertElement() { if (this.get('focused')) { Ember.run.schedule('afterRender', () => { this.send('startEditing'); }); Ember.run.next(this, this.setInputFocus); } // Prevent default / bubbling of keypress event when pressing enter Ember.$('#' + this.get('inputId')) .keypress((e) => e.which !== 13); }, inputId: Ember.computed('elementId', function() { return this.get('elementId') + '-input'; }), displayedValue: Ember.computed('value', 'viewValue', 'focused', { get() { if (this.get('focused')) { return this.get('viewValue'); } else { return this.get('value'); } }, set(key, value, cachedValue) { if (this.get('focused')) { this.set('viewValue', value); return value; } else { return cachedValue; } } }), updateInputFocus: Ember.observer('focused', function() { Ember.run.scheduleOnce('afterRender', this, this.setInputFocus); }), setInputFocus() { const inputElement = Ember.$('#' + this.get('inputId')).get(0); if (inputElement && this.get('focused')) { inputElement.focus(); if (this.get('autoSelect')) { inputElement.select(); } } else { if (!this.get('isDestroying')) { inputElement.blur(); } } }, validateName(name) { return typeof this.attrs.validate !== 'function' || this.attrs.validate(name); }, actions: { startEditing() { this.setProperties({ focused: true, viewValue: this.get('value') }); }, cancelEditing() { this.setProperties({ focused: false, viewValue: null }); }, endEditing(reason) { const value = this.get('viewValue'); ensurePromise(this.validateName(value)).then(isValid => { if (!isValid) { Ember.run.next(this, this.setInputFocus); } else { this.setProperties({ focused: false, value: value, viewValue: null }); if (reason === 'enter' && this.attrs.onEnterPress && this.attrs.onEnterPress.call) { this.attrs.onEnterPress(value); } if (this.attrs.onChange && this.attrs.onChange.call) { this.attrs.onChange(value); } } }); } } }); ================================================ FILE: portiaui/app/components/colored-badge.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '', color: null, value: 0, badgeStyle: Ember.computed('color.main', function() { var color = this.get('color.main'); return Ember.String.htmlSafe(color ? `background-color: ${color};` : ''); }) }); ================================================ FILE: portiaui/app/components/colored-span.js ================================================ import Ember from 'ember'; const { computed } = Ember; export default Ember.Component.extend({ tagName: 'span', attributeBindings: ['colorStyle:style'], colorStyle: computed('color.main', function() { var color = this.get('color.main'); return Ember.String.htmlSafe(color ? `color: ${color};` : ''); }) }); ================================================ FILE: portiaui/app/components/combo-box.js ================================================ import Ember from 'ember'; import SelectBox from './select-box'; export default SelectBox.extend({ autoSelect: false, inputClass: null, spellcheck: true, query: Ember.computed('open', 'viewValue', 'valueAttribute', { get() { return this.getValueAttribute(this.get('viewValue')); }, set(key, value) { Ember.run.scheduleOnce('afterRender', this, this.updateViewValue); return value; } }), setInputFocus(ignoreAutoSelect = false) { const inputElement = Ember.$('#' + this.get('inputId')).get(0); if (inputElement && this.get('open')) { inputElement.focus(); if (!ignoreAutoSelect && this.get('autoSelect')) { inputElement.select(); } } else if (!this.get('isDestroying')) { inputElement.blur(); } }, getValueAttribute(value) { const valueAttribute = this.get('valueAttribute'); if (value && valueAttribute) { value = value.get ? value.get(valueAttribute) : value[valueAttribute]; } return value; }, updateViewValue() { const query = this.get('query'); let items = []; this.trigger('getMenuItems', items); if (this.orderItemsForSearch) { items = this.orderItemsForSearch(items); } const currentValue = this.getValueAttribute(this.get('viewValue')); if (currentValue !== query) { let item = items.find(item => { return this.getValueAttribute(item.get('value')) === query; }); if (!item && !currentValue.startsWith(query)) { item = items.find(item => { return this.getValueAttribute(item.get('value')).startsWith(query); }); } if (item) { this.set('viewValue', item.get('value')); } } }, actions: { restoreFocus() { if (this.get('open')) { Ember.run.next(this, this.setInputFocus, /* ignoreAutoSelect = */true); } } } }); ================================================ FILE: portiaui/app/components/create-project-button.js ================================================ import Ember from 'ember'; const { computed, inject: { service } } = Ember; export default Ember.Component.extend({ dispatcher: service(), capabilities: service(), tagName: '', canCreateProjects: computed.readOnly('capabilities.capabilities.create_projects'), projectName: null, actions: { addProject() { this.get('dispatcher').addProject(this.get('projectName'), /* redirect = */true); } } }); ================================================ FILE: portiaui/app/components/create-spider-button.js ================================================ import Ember from 'ember'; import {computedCanAddSpider} from '../services/dispatcher'; export default Ember.Component.extend({ browser: Ember.inject.service(), dispatcher: Ember.inject.service(), tagName: '', project: null, canAddSpider: computedCanAddSpider(), actions: { addSpider() { this.get('dispatcher').addSpider(this.get('project'), /* redirect = */true); } } }); ================================================ FILE: portiaui/app/components/data-structure-annotations.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), uiState: Ember.inject.service(), tagName: '', item: null, sample: null, annotationColors: [], actions: { enterAnnotation(annotation) { this.set('uiState.viewPort.hoveredModels', [annotation]); }, leaveAnnotation() { this.set('uiState.viewPort.hoveredModels', []); }, enterItem(item) { this.set('uiState.viewPort.hoveredModels', item.get('orderedAnnotations')); }, leaveItem() { this.set('uiState.viewPort.hoveredModels', []); }, removeAnnotation(annotation) { this.get('dispatcher').removeAnnotation(annotation); }, removeItem(item) { this.get('dispatcher').removeItem(item); }, saveItem(item) { item.save(); } } }); ================================================ FILE: portiaui/app/components/data-structure-listing.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), tagName: '', annotationColors: [], actions: { addItem(sample) { this.get('dispatcher').addItem(sample, /* redirect = */true); }, removeItem(item) { this.get('dispatcher').removeItem(item); } } }); ================================================ FILE: portiaui/app/components/dropdown-delete.js ================================================ import Ember from 'ember'; const { computed } = Ember; export default Ember.Component.extend({ tagName: 'li', classNames: ['dropdown-delete'], classNameBindings: ['isConfirmed'], isConfirmed: false, notConfirmed: computed.not('isConfirmed'), actions: { onDelete() { if (this.get('notConfirmed')) { this.set('isConfirmed', true); } else { this.get('onDelete')(); } } } }); ================================================ FILE: portiaui/app/components/dropdown-divider.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'li', classNames: ['divider'], attributeBindings: ['role'], role: 'separator' }); ================================================ FILE: portiaui/app/components/dropdown-header.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'li', classNames: ['dropdown-header'] }); ================================================ FILE: portiaui/app/components/dropdown-item.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'li', classNames: ['dropdown-item'], classNameBindings: ['active', 'focused', 'disabled'], disabled: false, menu: null, value: null, active: Ember.computed('menu.activeItem', function() { return this.get('menu.activeItem') === this; }), focused: Ember.computed('menu.focusedItem', function() { return this.get('menu.focusedItem') === this; }), didInsertElement() { const menu = this.get('menu'); if (menu) { menu.registerItem(this); } }, willDestroyElement() { const menu = this.get('menu'); if (menu) { menu.unRegisterItem(this); } }, actions: { performAction(value) { if (this.attrs.action && !this.get('disabled')) { this.attrs.action(value); } } } }); ================================================ FILE: portiaui/app/components/dropdown-menu.js ================================================ import Ember from 'ember'; function computedItem(propertyName) { const cachePropertyName = `_${propertyName}ItemCache`; return Ember.computed(propertyName, 'items', { get() { let cachedItem = this[cachePropertyName]; const value = this.get(propertyName); let items = this.get('items'); if (!cachedItem || !items.includes(cachedItem) || cachedItem.get('value') !== value) { if (this.orderItemsForSearch) { items = this.orderItemsForSearch(items); } const equalityFn = this.valuesEqual || Ember.isEqual; this[cachePropertyName] = cachedItem = items.find(item => equalityFn(item.get('value'), value)); } return cachedItem; }, set(key, item) { this[cachePropertyName] = item; this.set(propertyName, item.get('value')); return item; } }); } export default Ember.Component.extend({ tagName: 'ul', attributeBindings: ['tabindex'], classNames: ['dropdown-menu'], active: null, focused: null, keyNavigate: 'active', tabindex: -1, items: Ember.computed(function() { if (!this.element) { return []; } const items = []; for (let child of this.element.children) { const item = this.itemsMap.get(child.id); if (item) { items.push(item); } } return items; }).volatile(), activeItem: computedItem('active'), focusedItem: computedItem('focused'), init() { this._super(); this.itemsMap = new Map(); this.getWithDefault('events', this) .on('menuKeyDown', this, this.keyDown) .on('getMenuItems', result => { result.push(...this.get('items')); }); }, next(type) { type = this.validateType(type); const items = this.get('items'); let item = this.get(`${type}Item`); const startIndex = items.indexOf(item); let index = startIndex; do { if (!~index) { index = 0; } else { index++; } index = (index + items.length) % items.length; item = items[index]; } while (item.get('disabled') && index !== startIndex); if (index !== startIndex) { this.set(`${type}Item`, item); } }, previous(type) { type = this.validateType(type); const items = this.get('items'); let item = this.get(`${type}Item`); const startIndex = items.indexOf(item); let index = startIndex; do { if (!~index) { index = -1; } else { index--; } index = (index + items.length) % items.length; item = items[index]; } while (item.get('disabled') && index !== startIndex); if (index !== startIndex) { this.set(`${type}Item`, item); } }, triggerAction(type) { type = this.validateType(type); const currentItem = this.get(`${type}Item`); if (currentItem) { currentItem.send('performAction'); } return !!currentItem; }, validateType(type, fallback) { if (!fallback) { fallback = this.validateType(this.get('keyNavigate'), 'active'); } return (type === 'active' || type === 'focused') ? type : fallback; }, focusIn() { if (this.attrs.onFocusIn) { this.attrs.onFocusIn(...arguments); } }, focusOut() { if (this.attrs.onFocusOut) { this.attrs.onFocusOut(...arguments); } }, keyDown() { this.send('keyDown', ...arguments); }, registerItem(item) { this.itemsMap.set(item.get('elementId'), item); Ember.run.scheduleOnce('afterRender', this, this.updateItems); }, unRegisterItem(item) { this.itemsMap.delete(item.get('elementId')); Ember.run.scheduleOnce('afterRender', this, this.updateItems); }, updateItems() { if (!this.get('isDestroying')) { this.notifyPropertyChange('items'); } }, orderItemsForSearch(items) { return items; }, valuesEqual(a, b) { return Ember.isEqual(a, b); }, actions: { keyDown($event) { const keyNavigate = this.get('keyNavigate'); switch ($event.keyCode) { case 13: // ENTER if (!this.triggerAction(keyNavigate)) { return; } break; case 38: // UP this.previous(keyNavigate); break; case 40: // DOWN this.next(keyNavigate); break; default: return; } $event.preventDefault(); $event.stopPropagation(); } } }); ================================================ FILE: portiaui/app/components/dropdown-widget.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ positionMonitor: Ember.inject.service(), classNames: ['dropdown'], classNameBindings: ['open'], active: null, events: null, focused: null, focusMenu: false, keyNavigate: 'active', menuAlign: 'left', menuClass: null, menuContainer: null, open: false, isDisabled: false, alignRight: Ember.computed.equal('menuAlign', 'right'), menuClasses: Ember.computed('menuClass', 'menuContainer', 'open', 'alignRight', function() { const classes = [this.get('menuClass')]; if (this.get('menuContainer')) { classes.push('dropdown-menu-floating'); if (this.get('open')) { classes.push('open'); } } if (this.get('alignRight')) { classes.push('pull-right'); } return classes.join(' '); }), init() { this._super(); if (!this.get('events')) { this.set('events', this); } this.$menu = null; this.elementFocused = false; this.menuWidth = null; this.menuHeight = null; this.windowHeight = null; }, didInsertElement() { const container = this.get('menuContainer'); if (container) { const positionMonitor = this.get('positionMonitor'); const $menu = this.$menu = this.$('.dropdown-menu'); Ember.run.schedule('afterRender', () => { Ember.$(container).append($menu); positionMonitor.registerElement( this.element, this, this.updateMenuSize, this.updatePosition); Ember.run.scheduleOnce('afterRender', positionMonitor, positionMonitor.update); }); } }, willDestroyElement() { const $menu = this.$menu; if ($menu) { const element = this.element; Ember.run.schedule('render', () => { this.get('positionMonitor').unRegisterElement( element, this, this.updateMenuSize, this.updatePosition); $menu.remove(); }); } }, focusIn() { this.send('focusIn', ...arguments); }, focusOut() { this.send('focusOut', ...arguments); }, keyDown() { this.send('keyDown', ...arguments); }, updateMenuSize() { const $menu = this.$menu; this.menuWidth = $menu.outerWidth(); this.menuHeight = $menu.outerHeight(true); this.windowHeight = window.innerHeight; }, updatePosition(rects, boundingRect) { let positionLeft; let positionTop; if (this.get('alignRight')) { positionLeft = Math.round(boundingRect.right - this.menuWidth); } else { positionLeft = Math.round(boundingRect.left); } if (boundingRect.bottom + this.menuHeight > this.windowHeight) { // If it overflows under the screen, align top positionTop = Math.round(boundingRect.top - this.menuHeight); } else { positionTop = Math.round(boundingRect.bottom); } this.$menu.css({ top: `${positionTop}px`, left: `${positionLeft}px`, right: `auto` }); }, click() { const action = this.get('onClick'); if (action) { action(); } }, actions: { openMenu() { if (!this.get('isDisabled')) { this.set('open', true); } }, closeMenu(closeReason) { if (this.attrs.onClose) { this.attrs.onClose(closeReason || 'close'); } this.set('open', false); }, toggleMenu(closeReason) { if (this.get('open')) { this.send('closeMenu', closeReason || 'toggle'); } else { this.send('openMenu'); } }, focusIn() { this.elementFocused = true; }, focusOut() { this.elementFocused = null; Ember.run.next(() => { if (!this.isDestroyed && !this.elementFocused) { this.send('closeMenu', 'focus-out'); } }); }, keyDown(event) { if (this.get('open')){ if (event.keyCode === 27) { // ESCAPE this.send('closeMenu', 'escape'); } this.get('events').trigger('menuKeyDown', ...arguments); } } } }); ================================================ FILE: portiaui/app/components/edit-sample-button.js ================================================ import Ember from 'ember'; const { computed } = Ember; import { computedCanAddSample, computedEditableSample } from '../services/dispatcher'; export default Ember.Component.extend({ browser: Ember.inject.service(), dispatcher: Ember.inject.service(), tagName: '', spider: null, canAddSample: computedCanAddSample('spider'), disableSample: computed('canAddSample', 'browser.invalidUrl', function() { return !this.get('canAddSample') || this.get('browser.invalidUrl'); }), editableSample: computedEditableSample('spider'), startUrlDomains: Ember.computed('spider.startUrls', function() { let startUrlDomains = new Set(); for (let uri of this.get('spider.startUrls')) { let domains = this.getUrlDomain(uri); for (let d of domains) { startUrlDomains.add(d); } } return startUrlDomains; }), sameDomain: Ember.computed('browser.url', 'spider.startUrls', function() { const urlDomain = this.getUrlDomain(this.get('browser.url')); if (!urlDomain) { return true; } const startUrlDomains = this.get('startUrlDomains'); for (let d of urlDomain) { if (startUrlDomains.has(d)) { return true; } } return false; }), getUrlDomain(uri) { let a = document.createElement('a'); a.href = uri; let hostname = [a.hostname], splitHostname = hostname[0].split('.'); if (splitHostname[0].length === 1 || splitHostname[0] === 'www') { hostname.push(hostname[0].split('.').splice(1).join('.')); } return hostname; }, actions: { addSample() { this.get('dispatcher').addSample(this.get('spider'), /* redirect = */true); } } }); ================================================ FILE: portiaui/app/components/element-overlay.js ================================================ import Ember from 'ember'; import {attrChanged, attrValue} from '../utils/attrs'; export default Ember.Component.extend({ overlays: Ember.inject.service(), positionMonitor: Ember.inject.service(), tagName: '', positionMode: 'size', // or 'edges' init() { this._super(...arguments); this.set('rects', []); }, didInsertElement() { Ember.run.scheduleOnce('afterRender', this, this.notifyAddOverlay); }, willDestroyElement() { Ember.run.scheduleOnce('afterRender', this, this.notifyRemoveOverlay); }, notifyAddOverlay() { this.get('overlays').add(); }, notifyRemoveOverlay() { this.get('overlays').remove(); }, didReceiveAttrs({oldAttrs, newAttrs}) { if (attrChanged(oldAttrs, newAttrs, 'viewPortElement')) { const oldElement = oldAttrs && attrValue(oldAttrs.viewPortElement); const newElement = attrValue(newAttrs.viewPortElement); const positionMonitor = this.get('positionMonitor'); if (oldElement) { positionMonitor.unRegisterElement( oldElement, this, this.readContainerSize, this.updatePosition); } if (newElement) { Ember.run.schedule('afterRender', () => { positionMonitor.registerElement( newElement, this, this.readContainerSize, this.updatePosition); }); } } }, on(name, ...params) { this._super(...arguments); Ember.run.scheduleOnce('afterRender', ...params, this.get('rects')); }, readContainerSize(rects, boundingRect, element) { const view = element.ownerDocument.defaultView; if (view) { this.containerSize = { width: view.innerWidth, height: view.innerHeight }; } }, updatePosition(rects) { const overlayRects = []; let prevRect = null; let length = this.get('rects').length; for (let rect of Array.from(rects)) { const left = Math.round(Math.min(this.containerSize.width, Math.max(0, rect.left))); const right = Math.round(Math.min(this.containerSize.width, Math.max(0, rect.right))); const top = Math.round(Math.min(this.containerSize.height, Math.max(0, rect.top))); const bottom = Math.round(Math.min(this.containerSize.height, Math.max(0, rect.bottom))); const width = right - left; const height = bottom - top; if (prevRect && top === prevRect.top && bottom === prevRect.bottom && (left === prevRect.right || right === prevRect.left)) { // merge neighbouring rects to minimize amount of rendered/animated elements prevRect.left = Math.min(left, prevRect.left); prevRect.right = Math.max(right, prevRect.right); prevRect.width += width; } else { prevRect = { left, right, top, bottom, width, height }; overlayRects.push(prevRect); } } // never shrink the number of elements, so that they can be animated out and are available // if needed again. length = Math.max(length, overlayRects.length); for (let i = overlayRects.length; i < length; i++) { overlayRects.push({}); } Ember.run.next(Ember.run.scheduleOnce, 'sync', () => { if (!this.isDestroying) { this.set('rects', overlayRects); } }); this.trigger('element-moved', overlayRects); } }); ================================================ FILE: portiaui/app/components/element-rect-overlay.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ classNames: ['overlay'], index: null, positionMode: 'size', backgroundStyle: Ember.computed('color.main', function() { const color = this.get('color.main'); return Ember.String.htmlSafe(color ? `background-color: ${color};` : ''); }), shadowStyle: Ember.computed('color.shadow', function() { const color = this.get('color.shadow'); return Ember.String.htmlSafe(color ? `box-shadow: 0 1px 3px -2px ${color};` : ''); }), textShadowStyle: Ember.computed('color.shadow', function() { const color = this.get('color.shadow'); return Ember.String.htmlSafe(color ? `text-shadow: 0 1px 1px ${color};` : ''); }), didInsertElement() { this.new = true; this.get('overlay').on('element-moved', this, this.updatePosition); }, willDestroyElement() { this.get('overlay').off('element-moved', this, this.updatePosition); }, updatePosition(rects) { if (!this.element) { return; } let index = this.get('index'); const rect = rects[index]; if (!rect) { return; } let { left, top, width, height } = rect; let hide = false; if (this.new || (!left && !top && !width && !height)) { hide = true; for (;index--;) { const lRect = rects[index]; const { left: lLeft, right: lRight, top: lTop, bottom: lBottom } = lRect; if (lLeft || lRight || lTop || lBottom) { left = lLeft; top = lBottom; height = 0; width = 0; break; } } if (this.new) { delete this.new; Ember.run.next( Ember.run.scheduleOnce, 'afterRender', this, this.updatePosition, rects); } } if (!left && !top && !width && !height) { return; } let style = ''; switch (this.get('positionMode')) { case 'size': style = `transform: translate(${left}px, ${top}px); width: ${width}px; height: ${height}px;`; break; case 'edges': // container is positioned in top left, and has zero width and height const right = -left + -width; const bottom = -top + -height; style = `left: ${left}px; right: ${right}px; top: ${top}px; bottom: ${bottom}px;`; break; } if (hide) { style = `opacity: 0; ${style}`; } this.element.setAttribute('style', style); } }); ================================================ FILE: portiaui/app/components/extracted-item-table.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'table', classNames: ['extracted-item-table'] }); ================================================ FILE: portiaui/app/components/extracted-items-group.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '' }); ================================================ FILE: portiaui/app/components/extracted-items-json-panel.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ extractedItems: Ember.inject.service(), tagName: '' }); ================================================ FILE: portiaui/app/components/extracted-items-json-value.js ================================================ import Ember from 'ember'; import { toType } from '../utils/types'; export default Ember.Component.extend({ tagName: 'span', classNames: ['json-value'], attributeBindings: ['style'], depth: 0, isString: Ember.computed('value', function () { return toType(this.get('value')) === 'string'; }), escapedValue: Ember.computed('value', function () { return JSON.stringify(this.get('value')); }), depthSpaces: Ember.computed('depth', function () { return ' '.repeat(this.get('depth')); }), fromArray: Ember.computed('from', function () { return this.get('from') === 'array'; }), comma: Ember.computed('position', function () { return this.get('position') < this.get('maxPosition') - 1 ? ',' : ''; }), style: Ember.computed('value', 'depth', 'key', 'from', function () { var textIndent = '', margin = '', width = '', characterTest = Ember.$('.json-character-size'), textWidth = characterTest.width(), extractedBox = Ember.$('.extracted-items-json'), extractedBoxWidth = extractedBox.width(), key = this.get('key') || '', value = this.get('escapedValue'), depth = this.get('depth'); if (this.get('isString') && ((depth + 1) * 2 + key.length + value.length + 4) * textWidth > extractedBoxWidth) { var indent = key.length; if (this.get('fromArray')) { indent = 2 * (depth + 1); textIndent = `text-indent: -${indent}ch;`; margin = `margin: 0 0 0 ${indent}ch;`; width = extractedBoxWidth; } else { textIndent = 'text-indent: -1ch;'; margin = 'margin: 0 0 0 1ch;'; width = extractedBoxWidth - (key.length + 4 + (depth + 1) * 2) * textWidth; width = `width: ${width}px`; } } return Ember.String.htmlSafe(`${textIndent}${margin}${width}`); }) }); ================================================ FILE: portiaui/app/components/extracted-items-json.js ================================================ import Ember from 'ember'; import { toType } from '../utils/types'; export default Ember.Component.extend({ tagName: '', position: 0, depth: -1, setDepth: function () { this.set('depth', this.getWithDefault('depth', -1) + 1); }.on('init'), isObject: Ember.computed('json', function () { return this._isObject(this.get('json')); }), isArray: Ember.computed('json', function () { return this._isArray(this.get('json')); }), isObjectOrArray: Ember.computed('isArray', 'isObject', function () { return this.get('isObject') || this.get('isArray'); }), fromKey: Ember.computed('from', function () { return this.get('from') === 'key'; }), comma: Ember.computed('position', 'parent', function () { return this.get('position') < this.get('maxPosition') - 1 ? ',' : ''; }), depthSpaces: Ember.computed('depth', 'isObjectOrArray', 'length', function () { if (this.get('isObjectOrArray') && !this.get('length')) { return ''; } return ' '.repeat(this.get('depth')); }), depthPlus1Spaces: Ember.computed('depth', function () { return ' '.repeat(this.get('depth') + 1); }), openingCharacter: Ember.computed('isObjectOrArray', function () { if (this.get('isArray')) { return '['; } else if (this.get('isObject')) { return '{'; } }), closingCharacter: Ember.computed('isObjectOrArray', function () { if (this.get('isArray')) { return ']'; } else if (this.get('isObject')) { return '}'; } }), maxPosition: Ember.computed('json', function () { var parent = this.get('parent'); if (parent) { return this._objLength(parent); } return -1; }), length: Ember.computed('json', function () { return this._objLength(this.get('json')); }), openChild: Ember.computed('json', function () { var child, json = this.get('json'); if (this.get('isObject')) { child = json[Object.keys(json)[0]]; } else if (this.get('isArray')) { child = json.get(0); } if (child) { return this._openNext(child); } }), openSibling: Ember.computed('json', 'parent', 'position', function () { var sibling, parent = this.get('parent'), position = this.get('position'); if (parent && position < parent.length - 1) { if (this._isObject(parent)) { sibling = parent[Object.keys(parent)[position + 1]]; } else if (this._isArray(parent)) { sibling = parent.get(position + 1); } if (sibling) { return this._openNext(sibling); } } }), showOpen: Ember.computed('json', function () { if ((this.get('isObject') && this.get('from') !== 'array') || (this.get('isArray') && this.get('from') !== 'object')) { return true; } return false; }), _openNext: function (next) { if (this._isObject(next)) { return '{'; } else if (this._isArray(next)) { return '['; } }, _isObject: function (obj) { return toType(obj) === 'object'; }, _isArray: function (obj) { return Array.isArray(obj); }, _objLength: function (obj) { if (this._isObject(obj)) { return Object.keys(obj).length; } else if (this._isArray(obj)) { return obj.length; } } }); ================================================ FILE: portiaui/app/components/extracted-items-panel.js ================================================ import Ember from 'ember'; const { inject: { service }, computed } = Ember; export default Ember.Component.extend({ tagName: '', extractedItems: service(), isExtracting: computed.readOnly('extractedItems.isExtracting'), failedMsg: computed.readOnly('extractedItems.failedExtractionMsg'), failedExtraction: computed.readOnly('extractedItems.failedExtraction') }); ================================================ FILE: portiaui/app/components/extracted-items-status.js ================================================ import Ember from 'ember'; const { computed, inject: { service } } = Ember; export default Ember.Component.extend({ tagName: '', extractedItems: service(), store: service(), type: computed.readOnly('extractedItems.type'), spider: computed.readOnly('extractedItems.spider'), changes: computed('extractedItems.changes', function() { return (this.get('extractedItems.changes') || []); }), changed: computed('extractedItems.changed', function() { return (this.get('extractedItems.changed') || []); }), hasWarning: computed('type', 'changes.[]', function() { let hasChanges = this.get('changes').length > 0; if (this.get('type') === 'js') { if (hasChanges && this.get('changes')[0] === 'no_items') { return false; } else { return true; } } return hasChanges; }), change: computed('hasWarning', function() { let change = this.get('changes')[0]; return change ? change : 'js_not_required'; }), changeInfo: computed('change', function() { let change = this.get('change'), changes = this.get('changed'), type = this.get('type'); if (change === 'missing_items' || change === 'missing_fields') { // TODO: Properly handle these conditions change = type === 'js' ? 'no_items' : 'js_not_required'; } let CHANGES = { js_not_required: { text: `Javascript is enabled for this sample and may not be needed. \ Your spider may run faster if Javascript is not run on pages like this`, path: 'projects.project.spider.options', }, no_items: { text: `Javascript is not enabled for this sample. It may extract more accurate \ data if it is enabled`, path: 'projects.project.spider.options', }, missing_required_field: { path: 'projects.project.schema.field.options', } }; let opts = CHANGES[change]; if (!opts) { return {}; } if (change === 'missing_required_field') { let field = this.get('store').peekRecord('field', changes[1][0]), text = `The field "${field.get('name')}" is marked as required but there is no \ annotation for that field`; opts.text = text; opts.model = field; return opts; } opts.model = this.get('spider'); return opts; }), icon: computed('hasWarning', function() { return this.get('hasWarning') ? 'warning-triangle' : 'ok'; }), }); ================================================ FILE: portiaui/app/components/extracted-items-tab.js ================================================ import Ember from 'ember'; const { inject: { service }, computed } = Ember; export default Ember.Component.extend({ extractedItems: service(), numItems: computed.readOnly('extractedItems.items.length'), isExtracting: computed.alias('extractedItems.isExtracting') }); ================================================ FILE: portiaui/app/components/extractor-options.js ================================================ import Ember from 'ember'; import { FIELD_TYPES } from '../models/field'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), tagName: '', annotation: null, types: FIELD_TYPES, project: Ember.computed.readOnly('annotation.parent.sample.spider.project'), regexExtractors: Ember.computed.filterBy('project.extractors', 'type', 'regex'), actions: { save() { this.get('annotation').save(); }, addTypeExtractor(type) { const annotation = this.get('annotation'); this.get('dispatcher').addAnnotationTypeExtractor(annotation, type); }, addRegexExtractor(extractor) { const annotation = this.get('annotation'); this.get('dispatcher').addAnnotationRegexExtractor(annotation, extractor); }, addNewRegexExtractor() { const annotation = this.get('annotation'); this.get('dispatcher').addNewAnnotationRegexExtractor(annotation); }, removeExtractor(extractor) { const annotation = this.get('annotation'); this.get('dispatcher').removeAnnotationExtractor(annotation, extractor); }, saveExtractor(extractor) { extractor.save().then(null, () => { extractor.rollbackAttributes(); }); } } }); ================================================ FILE: portiaui/app/components/feed-url-options.js ================================================ import Ember from 'ember'; import { cleanUrl } from '../utils/utils'; export default Ember.Component.extend({ feedLink: 'http://files.scrapinghub.com/portia/urls.txt', didRender() { this._super(...arguments); this.$('.focus-control').focus(); }, actions: { saveFeedUrl() { const url = cleanUrl(this.get('startUrl.url')); this.set('startUrl.url', url); this.get('saveSpider').perform(); } } }); ================================================ FILE: portiaui/app/components/field-options.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '', field: null, actions: { save() { this.get('field').save(); } } }); ================================================ FILE: portiaui/app/components/fragment-options.js ================================================ import Ember from 'ember'; const { computed, run } = Ember; import { task, timeout } from 'ember-concurrency'; import Changeset from 'ember-changeset'; import lookupValidator from 'ember-changeset-validations'; import { multiplicityFragment } from '../utils/start-urls'; import FixedFragmentValidations from '../validations/fixed-fragment'; import RangeFragmentValidations from '../validations/range-fragment'; import ListFragmentValidations from '../validations/list-fragment'; const TOOLTIP_DEBOUNCE = 1000; const TOOLTIP_DELAY = 2000; const VALIDATIONS = { 'fixed': FixedFragmentValidations, 'range': RangeFragmentValidations, 'list': ListFragmentValidations }; export default Ember.Component.extend({ tagName: 'form', classNames: ['fragment-form', 'form-inline'], toggleTooltip: false, fragmentTypes: [ { value: 'fixed', label: 'Fixed' }, { value: 'range', label: 'Range' }, { value: 'list', label: 'List' } ], fragmentType: computed('fragment.type', { get() { return this.get('fragmentTypes').findBy('value', this.get('fragment.type')); }, set(key, value) { this.changeFragmentType(value); this.focusFragment(); return value; } }), changeset: computed('fragment.type', function() { const validations = VALIDATIONS[this.get('fragment.type')]; return new Changeset( this.get('fragment'), lookupValidator(validations), validations ); }), isList: computed.equal('fragment.type', 'list'), isRange: computed.equal('fragment.type', 'range'), listPlaceholder: computed('isList', function() { return this.get('isList') ? 'val1 val2 val3' : ''; }), multiplicity: computed('fragmentType', 'fragment.value', function() { return multiplicityFragment(this.get('fragment')); }), limits() { const limits = this.get('changeset.value').split('-'); return limits.length !== 2 ? ['', ''] : limits; }, lower: computed('isRange', 'changeset.value', { get() { return this.limits()[0]; }, set(key, value) { this.updateLimit(value, 0); return value; } }), higher: computed('isRange', 'changeset.value', { get() { return this.limits()[1]; }, set(key, value) { this.updateLimit(value, 1); return value; } }), // helpers updateFragment() { this.saveChangeset(); this.set('toggleTooltip', false); this.get('flashTooltip').perform(); this.set('fragment.valid', this.get('changeset.isValid')); }, updateLimit(value, index) { let limits = this.limits(); limits[index] = value; const changeset = this.get('changeset'); changeset.set('value', limits.join('-')); this.updateFragment(); }, changeFragmentType(value) { this.set('fragment.value', ''); this.set('fragment.valid', true); this.set('fragment.type', value.value); }, focusFragment() { run.scheduleOnce('afterRender', this.context, () => { this.$('.focus-control').focus(); }); }, saveChangeset() { const changeset = this.get('changeset'); if (changeset.get('value') === '') { changeset.set('value', ''); } if (changeset.get('isValid')) { changeset.save(); } }, flashTooltip: task(function * () { yield timeout(TOOLTIP_DEBOUNCE); if (this.get('changeset.isInvalid')) { this.set('toggleTooltip', true); yield timeout(TOOLTIP_DELAY); this.set('toggleTooltip', false); } }).restartable(), actions: { saveFragment() { this.updateFragment(); if (this.get('changeset.isValid') && this.get('allValidFragments')) { this.get('saveSpider').perform(); } }, updateValue() { this.updateFragment(); }, changeFragmentType() { this.get('saveSpider').cancelAll(); } } }); ================================================ FILE: portiaui/app/components/generated-url-options.js ================================================ import Ember from 'ember'; const { computed } = Ember; import { getColors } from '../utils/colors'; import { multiplicityFragment } from '../utils/start-urls'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), rawColors: computed.mapBy('fragmentColors', 'main'), fragments: computed.alias('startUrl.fragments'), allValidFragments: computed('fragments.@each.valid', function() { return this.get('fragments').reduce((a, b) => { return (a.valid === undefined || a.valid) && (b.valid === undefined || b.valid); }); }), generatedUrlLists: computed('fragments.@each.type', 'fragments.@each.value', function() { return this.get('startUrl').generateList(); }), fragmentColors: computed('fragments.[]', function() { return getColors(this.get('fragments.length')); }), isComplete: computed('generatedUrlLists', '_fragmentCount', function() { return this.get('generatedUrlLists.length') === this.get('_fragmentCount'); }), actions: { addFragment() { this.get('dispatcher').addFragment(this.get('startUrl')); this.get('saveSpider').perform(); }, removeFragment(fragment) { this.get('dispatcher').removeFragment(this.get('startUrl'), fragment); this.get('saveSpider').perform(); } }, _fragmentCount: computed('fragments.@each.type', 'fragments.@each.value', function() { return this.get('fragments') .map(multiplicityFragment) .reduce((a,b) => a * b); }) }); ================================================ FILE: portiaui/app/components/help-icon.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '', tooltipClasses: null, tooltipContainer: 'body', placement: 'right', icon: 'help', classes: 'help-icon', }); ================================================ FILE: portiaui/app/components/icon-button.js ================================================ import Ember from 'ember'; export const ICON_CLASSES = { add: 'structure-list-add fa fa-plus-circle', 'add-dropdown': 'structure-list-add fa fa-play-circle fa-rotate-90', close: 'fa fa-times', code: 'fa fa-code', copy: 'fa fa-copy', 'data-annotation': 'fa fa-hand-pointer-o', date: 'fa fa-calendar', 'default-add': 'fa fa-check-circle structure-list-publish', 'default-remove': 'fa fa-times-circle structure-list-discard', download: 'fa fa-download', publish: 'structure-list-publish fa fa-cloud-upload', edit: 'fa fa-pencil', error: 'structure-list-error fa fa-exclamation-circle', 'error-triangle': 'structure-list-error fa fa-exclamation-triangle', file: 'fa fa-file', geopoint: 'fa fa-map-marker', help: 'icon-button-help fa fa-question-circle', image: 'fa fa-picture-o', link: 'fa fa-link', list: 'fa fa-list', navigation: 'fa fa-eye', number: 'portia-icon portia-icon-number', options: 'structure-list-details fa fa-cog', ok: 'structure-list-publish fa fa-check-circle', play: 'structure-list-play fa fa-play-circle', price: 'fa fa-dollar', project: 'fa fa-folder', 'raw html': 'fa fa-code', 'regular expression': 'portia-icon portia-icon-regex', remove: 'structure-list-remove fa fa-minus-circle', rollback: 'structure-list-discard fa fa-history', 'safe html': 'portia-icon portia-icon-safe-html', sample: 'fa fa-file', schema: 'fa fa-database', spider: 'portia-icon portia-icon-spider', structure: 'fa fa-sitemap', text: 'portia-icon portia-icon-text', 'tool-css': 'fa fa-file-code-o', 'tool-magic': 'fa fa-magic fa-flip-horizontal', 'tool-select': 'fa fa-mouse-pointer', 'tool-add': 'fa fa-plus', 'tool-remove': 'fa fa-minus', 'tool-multiple': 'fa fa-th-large', url: 'fa fa-globe', 'url-generated': 'portia-icon portia-icon-generated-url', 'url-feed': 'portia-icon portia-icon-feed-url', 'vertical-ellipsis': 'fa fa-ellipsis-v', 'warning-triangle': 'structure-list-warning fa fa-exclamation-triangle' }; export default Ember.Component.extend({ attributeBindings: ['tabindex'], classNames: ['icon-button'], classNameBindings: ['iconClasses', 'disabled', 'hasAction', 'modifyClasses'], tagName: 'i', bubbles: true, disabled: false, modifyClasses: '', hasAction: Ember.computed.bool('action'), beforeClick() {}, click() { this.beforeClick(); if (this.attrs.action && !this.get('disabled')) { this.attrs.action(); if (!this.get('bubbles')) { return false; } } }, iconClasses: Ember.computed('icon', function() { var icon = this.get('icon'); return ICON_CLASSES[icon] || 'fa'; }) }); ================================================ FILE: portiaui/app/components/indentation-spacer.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ classNames: ['indentation-spacer'], classNameBindings: ['isSmall'], isSmall: false }); ================================================ FILE: portiaui/app/components/input-with-clear.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ classNames: ['input-group', 'input-with-clear'], type: 'text', value: '', actions: { clear() { this.set('value', ''); this.get('clear')(); }, keyUp() { this.update(this.get('value')); } } }); ================================================ FILE: portiaui/app/components/inspector-panel.js ================================================ import Ember from 'ember'; import { pathSelector } from '../utils/selectors'; export const IGNORED_ATTRIBUTES = new Set([ 'id', 'class', 'target', 'width', 'style', 'height', 'cellpadding', 'cellspacing', 'border', 'bgcolor', 'color', 'colspan', 'data-scrapy-annotate', 'data-tagid', 'data-genid', 'data-parentid' ]); export function hasContentAttribute(element) { return Ember.$(element).attr('content') ? true : false; } export function getAttributeList(element) { if (!element) { return []; } var attributeList = []; var $element = Ember.$(element); var textContent = $element.text().trim(); if (textContent) { let hasContent = hasContentAttribute(element); attributeList.push({ name: hasContent ? 'text content' : 'content', attribute: hasContent ? 'text-content' : 'content', value: textContent }); } var mappedAttributes = {}; for (var i = 0; i < element.attributes.length; i++) { var attrib = element.attributes[i]; if (attrib.name.startsWith('data-portia-')) { var originalName = attrib.name.slice('data-portia-'.length); if (!mappedAttributes[originalName]) { mappedAttributes[originalName] = attrib.value; } } } Array.prototype.slice.call(element.attributes).forEach(function(attribute) { if (!attribute.nodeName.startsWith('data-portia-') && !IGNORED_ATTRIBUTES.has(attribute.nodeName) && attribute.value) { attributeList.push({ name: attribute.nodeName, attribute: attribute.nodeName, value: mappedAttributes[attribute.nodeName] || attribute.value }); } }); return attributeList; } export function getDefaultAttribute(element) { // TODO: Remove attributes that have been already annotated const attrList = getAttributeList(element); if (attrList.length === 1 && attrList[0].attribute) { // Only one possible attribute return attrList[0].attribute; } if (attrList.findBy('attribute', 'src')) { return 'src'; } else if (attrList.findBy('attribute', 'href')) { return 'href'; } else if (attrList.findBy('attribute', 'datetime')) { return 'datetime'; } else if (attrList.findBy('attribute', 'content')) { return 'content'; } else if (attrList.length) { return attrList[0].attribute; } return null; } export default Ember.Component.extend({ dispatcher: Ember.inject.service(), uiState: Ember.inject.service(), tagName: '', attributes: Ember.computed('inspectedElement', function() { return getAttributeList(this.get('inspectedElement')); }), elementPath: Ember.computed('inspectedElement', function() { const element = this.get('inspectedElement'); if (!element) { return ''; } return pathSelector(element); }), elementParents: Ember.computed('originalSelectedElement', 'selectedElement', function() { const inspected = this.get('originalSelectedElement'); const selected = this.get('selectedElement'); if (!inspected) { return []; } return $(inspected).add($(inspected).parents()).toArray().map(element => ({ element: element, tagName: element.tagName.toLowerCase(), selected: element === selected, isLast: element === inspected, })); }), elementChilds: Ember.computed('selectedElement', function() { const selected = this.get('selectedElement'); return $(selected).children().toArray().map(element => ({ element: element, tagName: element.tagName.toLowerCase() })); }), inspectedElement: Ember.computed.or( 'uiState.viewPort.hoveredElement', 'uiState.viewPort.selectedElement'), originalSelectedElement: Ember.computed.alias('uiState.viewPort.originalSelectedElement'), selectedElement: Ember.computed.alias('uiState.viewPort.selectedElement'), isHovered: Ember.computed.bool('uiState.viewPort.hoveredElement'), actions: { addAnnotation(attribute) { this.get('dispatcher').addAnnotation( /* auto item */null, this.get('inspectedElement'), attribute, /* redirect = */true); }, changeAnnotationSource(attribute) { const annotation = this.get('uiState.models.annotation'); this.get('dispatcher').changeAnnotationSource(annotation, attribute); }, selectParent(element) { this.set('selectedElement', element); }, selectChild(element) { this.set('selectedElement', element); // Selecting sideways resets the originalSelectedElement this.set('uiState.viewPort.originalSelectedElement', element); }, } }); ================================================ FILE: portiaui/app/components/link-crawling-options.js ================================================ import Ember from 'ember'; import SaveSpiderMixin from '../mixins/save-spider-mixin'; export default Ember.Component.extend(SaveSpiderMixin,{ tagName: '', spider: null, actions: { save() { this.saveSpider(); } } }); ================================================ FILE: portiaui/app/components/list-item-add-annotation-menu.js ================================================ import Ember from 'ember'; import config from '../config/environment'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), tagName: '', item: null, allowNesting: config.APP.allow_nesting, actions: { addAnnotation() { const item = this.get('item'); this.get('dispatcher').addAnnotation(item, undefined, undefined, /* redirect = */true); }, addNestedItem() { const item = this.get('item'); this.get('dispatcher').addNestedItem(item, /* redirect = */true); } } }); ================================================ FILE: portiaui/app/components/list-item-annotation-field.js ================================================ import Ember from 'ember'; import {validateFieldName} from './schema-structure-listing'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), notificationManager: Ember.inject.service(), tagName: '', annotation: null, selecting: false, actions: { validateFieldName(name) { return Ember.RSVP.all([ this.get('annotation.field'), this.get('annotation.parent.schema.fields') ]).then(([currentField, fields]) => { if (!fields) { return true; } fields = fields.reject(f => f === currentField); const error = validateFieldName(name, fields); if (error) { this.get('notificationManager').showWarningNotification(error); } return !error; }); }, addField(name) { const annotation = this.get('annotation'); const schema = annotation.get('field.schema'); const currentType = annotation.get('type'); const dispatcher = this.get('dispatcher'); dispatcher.addNamedField(schema, name, currentType, /* redirect = */false).then( field => { annotation.set('field', field); annotation.save(); }); }, changeField() { const annotation = this.get('annotation'); annotation.get('field').then(() => { annotation.set('field', annotation.get('field')); // Used to trigger updates annotation.save(); }); } } }); ================================================ FILE: portiaui/app/components/list-item-badge.js ================================================ import ColoredBadge from './colored-badge'; export default ColoredBadge.extend({ }); ================================================ FILE: portiaui/app/components/list-item-combo.js ================================================ import ListItemSelectable from './list-item-selectable'; export default ListItemSelectable.extend({ classNames: ['list-item-combo'], autoSelect: false }); ================================================ FILE: portiaui/app/components/list-item-editable.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ classNames: ['list-item-editable'], classNameBindings: ['editing'], editing: false, onChange: null, validate: null, spellcheck: true, value: null, click() { if (this.get('editing')) { return false; } }, actions: { startEditing() { this.set('editing', true); } } }); ================================================ FILE: portiaui/app/components/list-item-field-type.js ================================================ import Ember from 'ember'; import { FIELD_TYPES } from '../models/field'; import ensurePromise from '../utils/ensure-promise'; export default Ember.Component.extend({ tagName: '', field: null, types: FIELD_TYPES, actions: { saveField() { const field = this.get('field'); ensurePromise(field).then(field => { if (!!field) { field.save(); } }); } } }); ================================================ FILE: portiaui/app/components/list-item-icon-menu.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '', icon: null, actions: { clickIcon() { const action = this.get('onClick'); if (action) { action(); } } } }); ================================================ FILE: portiaui/app/components/list-item-icon.js ================================================ import IconButton from './icon-button'; export default IconButton.extend({ classNames: ['list-item-icon'], beforeClick() { const action = this.get('onClick'); if (action) { action(); } } }); ================================================ FILE: portiaui/app/components/list-item-item-schema.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), tagName: '', item: null, selecting: false, actions: { addSchema(name) { const item = this.get('item'); const project = item.get('schema.project'); this.get('dispatcher').addNamedSchema( project, name, /* redirect = */false).then((schema) => { item.set('schema', schema); item.save(); }); }, changeSchema() { const item = this.get('item'); item.get('schema').then(() => { item.set('schema', item.get('schema')); // Used to trigger updates item.save(); }); } } }); ================================================ FILE: portiaui/app/components/list-item-link-crawling.js ================================================ import Ember from 'ember'; import SaveSpiderMixin from '../mixins/save-spider-mixin'; const { computed, inject: { service } } = Ember; export default Ember.Component.extend(SaveSpiderMixin, { routing: service('-routing'), tagName: '', spider: null, followPatternOptions: [ { value: 'auto', label: 'Follow links automatically', description: `Use start urls and sample urls to teach the spider the \ best links to follow` }, { value: 'all', label: 'Follow all in-domain links', description: `Follow all links which have a domain or sub domain that match \ the start or sample urls` }, { value: 'none', label: "Don't follow links", description: `Only attempt to extract data from start urls. Can be combined \ to great effect with feed and generated urls` }, { value: 'patterns', label: 'Configure url patterns', description: `Create patterns for the spider to follow or not and direct your \ spider with pin point accuracy` }, ], linksToFollow: computed('spider.linksToFollow', { get() { return this.followPatternOptions.findBy('value', this.get('spider.linksToFollow')); }, set(key, value) { this.set('spider.linksToFollow', value.value); return value; } }), actions: { saveSpider() { this.saveSpider().then(() => { if (this.get('linksToFollow.value') === 'patterns') { this.get('routing').transitionTo('projects.project.spider.link-options'); } else if (this.get('linksToFollow.value') === 'none' && this.get('routing.currentRouteName').endsWith('link-options')) { this.get('routing').transitionTo('projects.project.spider'); } }); } } }); ================================================ FILE: portiaui/app/components/list-item-relation-manager.js ================================================ import Ember from 'ember'; import { ensurePromise } from '../utils/promises'; export default Ember.Component.extend({ tagName: '', onChange: null, choices: [], selecting: false, value: null, choicesOrdering: ['name'], sortedChoices: Ember.computed.sort('choices', 'choicesOrdering'), orderItemsForSearch(items) { function sortPriority(item) { switch (item.get('value.special')) { case 'rename': return 1; case 'add': return 2; default: return 0; } } return items.sort((a, b) => sortPriority(a) - sortPriority(b)); }, valuesEqual(a, b) { const aValue = a && (a.get ? a.get('name') : a.name); const bValue = b && (b.get ? b.get('name') : b.name); return aValue === bValue; }, validateName(name) { return typeof this.attrs.validate !== 'function' || this.attrs.validate(name); }, actions: { add(name) { ensurePromise(this.validateName(name)).then(isValid => { if (isValid) { if (this.attrs.create) { this.attrs.create(name); } } }); }, rename(name) { ensurePromise(this.validateName(name)).then(isValid => { if (isValid) { const model = this.get('value'); ensurePromise(model).then(item => { if (!item) { return; // Model is null } item.set('name', name); item.save(); }); } }); } } }); ================================================ FILE: portiaui/app/components/list-item-selectable.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ classNames: ['list-item-selectable'], classNameBindings: ['selecting'], change: null, choices: [], buttonClass: null, menuAlign: 'left', menuClass: null, menuContainer: null, selecting: false, value: null, actions: { startSelecting() { this.set('selecting', true); } } }); ================================================ FILE: portiaui/app/components/list-item-text.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'span', classNames: ['list-item-text'] }); ================================================ FILE: portiaui/app/components/notification-container.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ notificationManager: Ember.inject.service(), classNames: ['notifications'], _banners: [], _notifications: [], banners: Ember.computed('_banners.[]', 'notificationManager.banners.[]', function() { const lastBanners = this.get('_banners'); const banners = this.get('notificationManager.banners'); for (let banner of lastBanners) { Ember.set(banner, 'fading', true); } for (let banner of banners) { Ember.set(banner, 'fading', undefined); } lastBanners.addObjects(banners); return lastBanners; }), notifications: Ember.computed('_notifications.[]', 'notificationManager.notifications.[]', function() { const lastNotifications = this.get('_notifications'); const notifications = this.get('notificationManager.notifications'); for (let notification of lastNotifications) { Ember.set(notification, 'fading', true); } for (let notification of notifications) { Ember.set(notification, 'fading', undefined); } lastNotifications.addObjects(notifications); return lastNotifications; }), displayNotifications: Ember.computed('banners.length', 'notifications.[]', function() { const numBanners = this.get('banners.length'); const notifications = this.get('notifications'); return notifications.slice(0, Math.max(0, 4 - numBanners)); }), actions: { dismissNotification(notification) { this.get('notificationManager.notifications').removeObject(notification); }, fadeBanner(banner) { this.get('_banners').removeObject(banner); }, fadeNotification(notification) { this.get('_notifications').removeObject(notification); } } }); ================================================ FILE: portiaui/app/components/notification-message.js ================================================ import Ember from 'ember'; import { attrChangedTo } from '../utils/attrs'; export default Ember.Component.extend({ classNames: ['alert', 'notification', 'fade'], classNameBindings: ['alertType', 'show:in'], notification: null, closeAction: null, dismissable: false, show: false, showTime: 4000, // 4s message: Ember.computed.readOnly('notification.message'), title: Ember.computed.readOnly('notification.title'), type: Ember.computed.readOnly('notification.type'), alertType: Ember.computed('type', function() { const type = this.getWithDefault('type', 'info'); return `alert-${type}`; }), init() { this._super(); this.set('show', false); }, didReceiveAttrs({newAttrs, oldAttrs}) { if (attrChangedTo(oldAttrs, newAttrs, 'fade', true)) { this.fadeOut(); } }, didInsertElement() { Ember.run.next(this, 'fadeIn'); if (this.attrs.closeAction) { Ember.run.later(() => { this.attrs.closeAction(); }, this.showTime); } }, fadeIn() { if (!this.isDestroying) { this.set('show', true); } }, fadeOut() { this.set('show', false); }, transitionEnd() { if (!this.get('show')) { if (this.attrs.fadeAction) { this.attrs.fadeAction(); } } }, actions: { close: function() { if (this.attrs.closeAction) { this.attrs.closeAction(); } } } }); ================================================ FILE: portiaui/app/components/page-actions-editor.js ================================================ import Ember from 'ember'; const TYPES = ['click', 'set', 'wait']; export default Ember.Component.extend({ actionTypes: TYPES, pageActions: null, editing: null, addingNew: false, actions: { reorderPageAction: function(originalIndex, newIndex){ var pageActions = this.get('pageActions'); var action = pageActions[originalIndex]; pageActions.removeAt(originalIndex); pageActions.insertAt(newIndex, action); }, deletePageAction: function(index){ var pageActions = this.get('pageActions'); pageActions.removeAt(index); }, editPageAction: function(pageAction) { pageAction._edited = true; this.set('editing', pageAction); }, back: function() { this.set('editing', null); }, addContinue: function(){ this.set('addingNew', false); }, addNew: function() { var pa = Ember.Object.create({ type: "wait", _edited: true }); this.set('addingNew', true); this.set('editing', pa); this.get('pageActions').pushObject(pa); } }, }); ================================================ FILE: portiaui/app/components/project-list.js ================================================ import Ember from 'ember'; const { computed } = Ember; export default Ember.Component.extend({ store: Ember.inject.service(), classNames: ['project-list', 'list-group'], classNameBindings: [ 'showSearch', 'filteredProjects.length::empty', 'withinDropdown:project-within-dropdown', 'showSearch::not-searchable' ], withinDropdown: false, minSearchableProjects: 8, projects: [], searchTerm: '', isSelecting: computed.bool('selectProject'), emptySearchTerm: computed.equal('searchTerm', ''), showSearch: computed('projects', function() { return this.get('projects.length') > this.get('minSearchableProjects'); }), filteredProjects: computed('projects', 'searchTerm', function() { let term = this.get('searchTerm'); if (term.length === 0) { return this.get('projects'); } return this.get('store').peekAll('project').filter(function(item) { return item.get('name').toLowerCase().indexOf(term) > -1; }); }), actions: { search(value) { this.set('searchTerm', value.toLowerCase().trim()); }, clear() { const action = this.get('onClear'); if (action && this.get('emptySearchTerm')) { action(); } this.set('searchTerm', ''); }, selectProject(project) { const action = this.get('selectProject'); if (action) { action(project); } } } }); ================================================ FILE: portiaui/app/components/project-listing.js ================================================ import Ember from 'ember'; const { computed, inject: { service } } = Ember; export default Ember.Component.extend({ capabilities: service(), changes: service(), notificationManager: service(), tagName: '', project: null, isNoticed: false, deployable: computed.readOnly('capabilities.capabilities.deploy_projects'), versionControlled: computed.readOnly('capabilities.capabilities.version_control'), notVersionControlled: computed.not('versionControlled'), hasChanges: computed.readOnly('changes.hasChanges'), hasNoChanges: computed.not('hasChanges'), notPublished: computed.or('hasNoChanges', 'notVersionControlled'), isPublished: computed.not('notPublished'), notNoticed: computed.not('isNoticed'), isPulsing: computed.and('hasChanges', 'notNoticed'), downloadUrl: computed('project', function() { const link = this.get('project._internalModel._links.self'); return `${link}/download`; }), downloadCodeUrl: computed('downloadUrl', function() { return `${this.get('downloadUrl')}?format=code`; }), actions: { deploy() { this.get('project').deploy().then(data => { // Show user message and allow them to schedule spider this.get('notificationManager').showNotification( data.meta.title); }, data => { let error = data.errors[0]; if (error.status > 499) { throw data; } this.get('notificationManager').showNotification(error.title, error.detail); if (error.status === 409) { this.sendAction('conflict'); } }); }, publish() { this.get('project').publish().then(data => { // Show user message and allow them to schedule spider this.get('notificationManager').showNotification( data.meta.title); }, data => { let error = data.errors[0]; if (error.status > 499) { throw data; } this.get('notificationManager').showNotification(error.title, error.detail); if (error.status === 409) { this.sendAction('conflict'); } }); }, discard() { this.get('project').reset().then(() => { this.sendAction('reload'); }, data => { let error = data.errors[0]; if (error.status > 499) { throw data; } this.get('notificationManager').showNotification(error.title, error.detail); }); }, clickProjectOptions() { this.set('isNoticed', true); } } }); ================================================ FILE: portiaui/app/components/project-structure-listing.js ================================================ import Ember from 'ember'; const { computed, observer } = Ember; import {computedCanAddSpider} from '../services/dispatcher'; import { task, timeout } from 'ember-concurrency'; const LIMIT = 15; const FILTER_DEBOUNCE = 800; const TURN_PAGE_DEBOUNCE = 200; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), uiState: Ember.inject.service(), tagName: '', spiderSearch: '', isFiltering: false, didReceiveAttrs() { const spiders = this.get('sortedSpiders').slice(0, LIMIT); this._addCurrentSpider(spiders); this.set('spiders', spiders); this.set('filteredSpiders', this.get('sortedSpiders')); }, // Pagination currentPage: 0, hasPreviousPage: computed.gte('currentPage', 1), hasNextPage: computed('currentPage', 'filteredSpiders.length', function() { const max = (this.get('currentPage') + 1) * LIMIT; return max < this.get('filteredSpiders.length'); }), pagination: computed('currentSpider', 'currentPage', 'spiders.[]', function() { if (this.get('currentSpider')) { return ''; } if (this.get('filteredSpiders.length') <= LIMIT) { return ''; } const numSpiders = this.get('spiders.length'); const currentPage = this.get('currentPage'); const start = (currentPage * LIMIT) + 1; const end = Math.min((currentPage + 1) * LIMIT, start + numSpiders - 1); return `( ${start}-${end} )`; }), currentSpiderChanged: observer('currentSpider', function() { Ember.run.next(() => { this._addCurrentSpider(this.get('spiders')); this._addCurrentSpider(this.get('filteredSpiders')); }); }), turnPage: task(function * (offset) { this.set('isFiltering', true); yield timeout(TURN_PAGE_DEBOUNCE); this.set('isFiltering', false); const nextPage = this.get('currentPage') + offset; const start = nextPage * LIMIT; this.set('spiders', this.get('filteredSpiders').slice(start, start + LIMIT)); this.set('currentPage', nextPage); }).drop(), numSpiders: computed.readOnly('project.spiders.length'), canAddSpider: computedCanAddSpider(), currentSpider: computed.readOnly('uiState.models.spider'), noCurrentSpider: computed.not('currentSpider'), currentSchema: computed.readOnly('uiState.models.schema'), isLarge: computed.gt('project.spiders.length', LIMIT), sortedSpiders: computed.sort('project.spiders', function(spider, other_spider) { const [a, b] = [spider, other_spider].map((spider) => { return spider.get('id').toLowerCase(); }); if (a < b) { return -1; } else if (a > b) { return 1; } return 0; }), sawNewOrDeletedSpider: observer('project.spiders.length', function() { Ember.run.once(() => { let term = this.get('searchTerm') || ''; this.get('filterSpiders').perform(this.get('sortedSpiders'), term); }); }), filterSpiders: task(function * (spiders, term) { this.set('isFiltering', true); yield timeout(FILTER_DEBOUNCE); this._updateFilter(this._fuzzyFilter(spiders, term), term); }).restartable(), addSpiderTooltipText: computed('canAddSpider', { get() { if (this.get('canAddSpider')) { return 'Create a new Spider'; } else { return 'You must visit a website before you can create a Spider'; } } }), actions: { addSchema() { this.get('dispatcher').addSchema(this.get('project'), /* redirect = */true); }, removeSchema(schema) { this.get('dispatcher').removeSchema(schema); }, setSchemaDefault(schema) { this.get('project.schemas').filterBy('default').forEach((s) => s.set('default', false)); schema.set('default', true); schema.save(); }, removeSchemaDefault(schema) { schema.set('default', false); schema.save(); }, saveSchema(schema) { schema.save(); }, addSpider() { this.get('dispatcher').addSpider(this.get('project'), /* redirect = */true); } }, _fuzzyFilter(items, term) { if (term === '') { return this.get('sortedSpiders'); } const fuzzy = new RegExp(term.split('').join('.*'), 'i'); return items.filter((item) => { return fuzzy.exec(item.get('id')); }); }, _addCurrentSpider(spiders) { const currentSpider = this.get('currentSpider'); if (currentSpider && !spiders.includes(currentSpider)) { spiders.pushObject(currentSpider); } }, _updateFilter(spiders, term = '') { this.set('spiderSearch', term); this.set('currentPage', 0); this.set('isFiltering', false); this.set('spiders', spiders.slice(0, LIMIT)); this.set('filteredSpiders', spiders); } }); ================================================ FILE: portiaui/app/components/project-structure-spider-feed-url.js ================================================ import Ember from 'ember'; const { computed } = Ember; import { cleanUrl } from '../utils/utils'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), tagName: '', url: computed.alias('startUrl.url'), isEditing: computed.equal('url', ''), viewUrl: computed('url', { get() { return this.get('url'); }, set(key, value) { this.saveStartUrl(value); } }), saveStartUrl(url) { this.set('startUrl.url', cleanUrl(url)); this.get('spider').save(); } }); ================================================ FILE: portiaui/app/components/project-structure-spider-generated-url.js ================================================ import Ember from 'ember'; const { computed } = Ember; export default Ember.Component.extend({ tagName: '', fragments: computed.alias('startUrl.fragments'), url: computed('startUrl.url', 'fragments.@each.type', 'fragments.@each.value', function() { return this.get('startUrl').show(); }) }); ================================================ FILE: portiaui/app/components/project-structure-spider-url.js ================================================ import Ember from 'ember'; const { computed } = Ember; import { cleanUrl } from '../utils/utils'; export default Ember.Component.extend({ dispatcher: Ember.inject.service(), tagName: '', fragments: computed.alias('startUrl.fragments'), url: computed('startUrl.url', 'fragments.@each.type', 'fragments.@each.value', function() { return this.get('startUrl').show(); }), viewUrl: Ember.computed('url', { get() { return this.get('url'); }, set(key, value, oldValue) { this.send('saveStartUrl', oldValue, value); return value; } }), handleNewUrl(oldUrl, newUrl) { const spider = this.get('spider'); const cleanNewUrl= cleanUrl(newUrl); if (!oldUrl) { this.get('dispatcher').addStartUrl(spider, cleanNewUrl); } else { this.get('dispatcher').replaceStartUrl(spider, oldUrl, cleanNewUrl); } }, removeStartUrl() { this.get('dispatcher').removeStartUrl(this.get('spider'), this.get('startUrl')); }, actions: { saveStartUrl(oldUrl, newUrl) { if (oldUrl !== newUrl) { if (newUrl) { this.handleNewUrl(oldUrl, newUrl); } else { this.removeStartUrl(); } } } } }); ================================================ FILE: portiaui/app/components/regex-pattern-list.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ classNames: ['regex-pattern-list'], list: [], newPattern: '', newPatternCorrect: Ember.computed('newPattern', function() { const pattern = this.get('newPattern'); try { new RegExp(pattern); } catch (e) { return false; } return true; }), triggerChange() { if (this.attrs.onChange) { this.attrs.onChange(); } }, actions: { addPattern(pattern) { if (this.get('newPattern') && this.get('newPatternCorrect')) { this.set('newPattern', ''); this.get('list').addObject(pattern); this.triggerChange(); } }, clearPattern() { this.set('newPattern', ''); }, changePattern(index, value) { const list = this.get('list'); const current = list.objectAt(index); if (value !== current) { list.removeObject(value); list.replace(list.indexOf(current), 1, [value]); this.triggerChange(); } }, removePattern(index) { this.get('list').removeAt(index); this.triggerChange(); }, stopPropagation($event) { $event.stopPropagation(); } } }); ================================================ FILE: portiaui/app/components/reorder-handler.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ attributeBindings: ['draggable', 'style'], draggable: true, tagName: 'i', classNames: 'fa fa-icon fa-arrows reorder-handler', dragStart: function(event) { var dataTransfer = event.originalEvent.dataTransfer; dataTransfer.effectAllowed = "move"; dataTransfer.setData('text/plain', ""); var dragElement = this.$().parentsUntil('.reorderable-list').eq(-1); dataTransfer.addElement(dragElement[0]); dragElement.addClass('dragging').one("dragend", function(){ dragElement.removeClass('dragging'); }); }, }); ================================================ FILE: portiaui/app/components/save-status.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ clock: Ember.inject.service(), savingNotification: Ember.inject.service(), tagName: 'p', classNames: ['save-status', 'text-center'], minSavingTime: 1000, // 1s minSuccessTime: 5000, // 5s init() { this._super(...arguments); this.wasSaving = false; }, isSaving: Ember.computed('savingNotification.isSaving', { get() { const isSaving = this.get('savingNotification.isSaving'); if (isSaving) { this.startTime = +new Date(); Ember.run.cancel(this.savingSchedule); return true; } else { const timeLeft = Math.max(0, this.minSavingTime - (+new Date() - this.startTime)); if (timeLeft) { this.savingSchedule = Ember.run.later(() => { this.set('isSaving', this.get('savingNotification.isSaving')); }, timeLeft); return true; } return false; } }, set(key, value) { return value; } }), timeSinceLastSave: Ember.computed('clock.time', 'savingNotification.lastSaved', function() { const current = this.get('clock.time'); const last = this.get('savingNotification.lastSaved'); if (!current || !last) { return null; } return moment(last).fromNow(); }), labelColorClass: Ember.computed('isSaving', { get() { const isSaving = this.get('isSaving'); if (isSaving) { this.wasSaving = true; Ember.run.cancel(this.colorSchedule); } else if (this.wasSaving) { this.wasSaving = false; this.colorSchedule = Ember.run.later(() => { this.set('labelColorClass', this.get('isSaving') ? 'info' : 'default'); }, this.minSuccessTime); return 'success'; } return isSaving ? 'info' : 'default'; }, set(key, value) { return value; } }) }); ================================================ FILE: portiaui/app/components/schema-structure-listing.js ================================================ import Ember from 'ember'; import ensurePromise from '../utils/ensure-promise'; export function validateFieldName(name, fields) { // Ensuring that field names don't start with underscores prevents // overwriting _item, _template and any future "protected" property // we might add to extracted items. if (/^_/.test(name)) { return "Invalid field name: field can't start with underscores"; } else if (name === 'url') { return ('Invalid field name: naming a field "url" is not allowed as' + 'there is already a field with this name'); } else if (fields.findBy('name', name)) { return 'Invalid field name: There is already a field with that name'; } return null; // No error } export default Ember.Component.extend({ notificationManager: Ember.inject.service(), dispatcher: Ember.inject.service(), tagName: '', actions: { addField() { this.get('dispatcher').addField(this.get('schema'), undefined, /* redirect = */true); }, removeField(field) { this.get('dispatcher').removeField(field); }, validateFieldName(field, name) { return this.get('schema.fields').then(fields => { fields = fields.reject(f => f === field); const error = validateFieldName(name, fields); if (error) { this.get('notificationManager').showWarningNotification(error); } return !error; }); }, saveField(field) { ensurePromise(field).then(field => { if (!!field) { field.save(); } }); } } }); ================================================ FILE: portiaui/app/components/scrapinghub-links.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '', }); ================================================ FILE: portiaui/app/components/select-box.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '', choices: [], buttonClass: null, menuAlign: 'left', menuClass: null, menuContainer: null, name: null, open: false, value: null, valueAttribute: null, isDisabled: false, viewValue: Ember.computed('value', { get() { return this.get('value'); }, set(key, value) { return value; } }), didInsertElement() { if (this.get('open')) { Ember.run.next(this, this.setInputFocus); } }, inputId: Ember.computed('elementId', function() { return this.get('elementId') + '-input'; }), updateInputFocus: Ember.observer('open', function() { Ember.run.scheduleOnce('afterRender', this, this.setInputFocus); }), setInputFocus() { const inputElement = Ember.$('#' + this.get('inputId')).get(0); if (inputElement && this.get('open')) { inputElement.focus(); } else if (!this.get('isDestroying')) { inputElement.blur(); } }, actions: { setViewValue(value) { this.set('viewValue', value); }, setValue(value) { this.setProperties({ value, viewValue: value }); }, setValueAndClose(value) { this.setProperties({ open: false, value }); if (this.attrs.onChange) { this.attrs.onChange(); } }, menuClicked() { const action = this.get('onClick'); if (action) { action(); } }, menuClosed(reason) { if (this.get('open')) { if (reason === 'escape') { this.setProperties({ open: false, viewValue: this.get('value') }); } else { const viewValue = this.get('viewValue'); if (viewValue && viewValue.onMenuClosed && viewValue.onMenuClosed.call) { viewValue.onMenuClosed(); } else { this.setProperties({ open: false, value: viewValue }); } if (this.attrs.onChange) { this.attrs.onChange(); } } } } } }); ================================================ FILE: portiaui/app/components/show-links-button.js ================================================ import Ember from 'ember'; const { computed, inject: { service } } = Ember; export default Ember.Component.extend({ browser: service(), disableLinks: computed.readOnly('browser.invalidUrl'), spider: null, actions: { toggleShowLinks() { const spider = this.get('spider'); spider.toggleProperty('showLinks'); spider.save(); } } }); ================================================ FILE: portiaui/app/components/show-links-legend.js ================================================ import Ember from 'ember'; import { NAMED_COLORS } from '../utils/colors'; export default Ember.Component.extend({ tagName: '', colors: NAMED_COLORS, followedLinks: 0, jsLinks: 0, ignoredLinks: 0 }); ================================================ FILE: portiaui/app/components/sliding-main.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ uiState: Ember.inject.service(), tagName: 'main', classNameBindings: ['slideRight'], slideRight: Ember.computed.bool('uiState.slideMain') }); ================================================ FILE: portiaui/app/components/spider-indentation.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '' }); ================================================ FILE: portiaui/app/components/spider-message.js ================================================ import Ember from 'ember'; const { computed } = Ember; export default Ember.Component.extend({ api: Ember.inject.service(), notificationManager: Ember.inject.service(), hasSpider: computed.bool('currentSpider'), actions: { runSpider(spider) { this.get('api').post('schedule', { model: spider, jsonData: {data: {type: 'spiders', id: spider.id}} }).then(() => { this.get('notificationManager').showNotification( 'Your spider has been scheduled successfully'); }, data => { let error = data.errors[0]; if (error.status > 499) { throw data; } this.get('notificationManager').showNotification(error.title, error.detail); }); } } }); ================================================ FILE: portiaui/app/components/spider-options.js ================================================ import Ember from 'ember'; import SaveSpiderMixin from '../mixins/save-spider-mixin'; export default Ember.Component.extend(SaveSpiderMixin, { tagName: '', spider: null, actions: { save() { this.saveSpider(); } } }); ================================================ FILE: portiaui/app/components/spider-row.js ================================================ import Ember from 'ember'; const { computed, inject: { service } } = Ember; export default Ember.Component.extend({ tagName: '', store: service(), uiState: service(), dispatcher: service(), savingNotification: service(), notificationManager: service(), projects: [], isCopyingSpider: false, init() { this._super(...arguments); const projectId = this.get('project.id'); this.set('projects', this.get('store').peekAll('project').rejectBy('id', projectId)); }, currentSpider: computed.readOnly('uiState.models.spider'), downloadUrl: computed('spider', function() { const link = this.get('spider._internalModel._links.self'); return `${link}/download`; }), downloadCodeUrl: computed('downloadUrl', function() { return `${this.get('downloadUrl')}?format=code`; }), notifyError(spider) { const msg = `Renaming the spider '${spider.get('id')}' failed.`; this.get('notificationManager').showErrorNotification(msg); spider.set('name', spider.get('id')); }, actions: { validateSpiderName(spider, name) { const nm = this.get('notificationManager'); if(!/^[a-zA-Z0-9][a-zA-Z0-9_\.-]*$/.test(name)) { nm.showWarningNotification(`Invalid spider name. Only letters, numbers, underscores, dashes and dots are allowed.`); return false; } if (spider.get('id') === name) { return true; } const spiders = this.get('project.spiders').mapBy('id'); if(spiders.indexOf(name) >= 0) { nm.showWarningNotification(`Invalid spider name. A spider already exists with the name "${name}"`); return false; } return true; }, removeSpider(spider) { this.get('dispatcher').removeSpider(spider); }, saveSpiderName(spider) { const dispatcher = this.get('dispatcher'); const saving = this.get('savingNotification'); saving.start(); dispatcher.changeSpiderName(spider) .then((data) => dispatcher.changeId(spider, data)) .catch(() => this.notifyError(spider)) .finally(() => saving.end()); }, closeSpiderOptions() { this.set('isCopyingSpider', false); }, copySpider() { this.set('isCopyingSpider', true); }, copyToProject(options, project) { project.copy({ from: this.get('project.id'), data: [ { id: this.get('spider.id'), type: 'spiders' } ] }).then(this._copyProjectSuccess(project)) .catch(this._copyProjectError.bind(this)) .finally(this._afterCopyProject(options)); } }, _copyProjectSuccess(project) { return () => { const msg = `Spider ${this.get('spider.id')} copied successfully to project ${project.get('name')}.`; this.get('notificationManager').showNotification(msg); }; }, _copyProjectError(data) { const error = data.errors[0]; if (error.status > 499) { throw data; } this.get('notificationManager').showErrorNotification(error.title, error.detail); }, _afterCopyProject(options) { return () => { options.closeMenu(); this.set('isCopyingSpider', false); }; } }); ================================================ FILE: portiaui/app/components/spider-structure-listing.js ================================================ import Ember from 'ember'; import {computedCanAddSample} from '../services/dispatcher'; export default Ember.Component.extend({ browser: Ember.inject.service(), dispatcher: Ember.inject.service(), uiState: Ember.inject.service(), tagName: '', project: null, spider: null, newStartUrl: null, canAddSample: computedCanAddSample('spider'), currentSample: Ember.computed.readOnly('uiState.models.sample'), init() { this._super(); this.set('newUrl', false); }, getNewStartUrl(newUrl) { let newStartUrl = ''; if (newUrl) { const spider = this.get('spider'); newStartUrl = this.get('dispatcher').addStartUrl(spider, newUrl); } return newStartUrl; }, getNewUrl() { let newUrl = this.get('browser.url') || ''; const urls = this.get('spider.startUrls').mapBy('url'); if (newUrl && urls.includes(newUrl)) { newUrl = ''; } return newUrl; }, actions: { addStartUrl() { this.get('closeOptions')(); const newUrl = this.getNewUrl(); this.setProperties({ newUrl: true, urlValue: newUrl, newStartUrl: this.getNewStartUrl(newUrl) }); }, addGenerationUrl() { const spider = this.get('spider'); let newUrl = this.get('browser.url') || ''; let newStartUrl = this.get('dispatcher').addGeneratedUrl(spider, newUrl); this.get('transitionToFragments')(spider.get('startUrls').indexOf(newStartUrl)); }, addFeedUrl() { const spider = this.get('spider'); let newStartUrl = this.get('dispatcher').addFeedUrl(spider, ''); this.get('transitionToFragments')(spider.get('startUrls').indexOf(newStartUrl)); }, removeStartUrl(startUrl) { this.get('dispatcher').removeStartUrl(this.get('spider'), startUrl); this.get('closeOptions')(); }, addSample() { this.get('dispatcher').addSample(this.get('spider'), /* redirect = */true); }, removeSample(sample) { this.get('dispatcher').removeSample(sample); }, saveSample(sample) { sample.save(); } } }); ================================================ FILE: portiaui/app/components/start-url-options.js ================================================ import Ember from 'ember'; const { computed } = Ember; import { task, timeout } from 'ember-concurrency'; const SPIDER_DEBOUNCE = 1000; export default Ember.Component.extend({ startUrl: computed('spider.startUrls.[]', 'startUrlId', function() { return this.get('spider').get('startUrls').objectAt(this.get('startUrlId')); }), title: computed.alias('startUrl.optionsTitle'), saveSpider: task(function * () { yield timeout(SPIDER_DEBOUNCE); this.get('spider').save(); }).restartable() }); ================================================ FILE: portiaui/app/components/tool-group.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ uiState: Ember.inject.service(), classNames: ['tool-group'], classNameBindings: ['collapsed'], onClose: false, collapsible: true, collapsed: false, selected: null, init() { this._super(); const id = this.get('elementId'); Ember.mixin(this, { selected: Ember.computed.alias('uiState.selectedTools.' + id), collapsed: Ember.computed.alias('uiState.collapsedPanels.' + id) }); }, actions: { close() { if (this.attrs.onClose) { this.attrs.onClose(); } }, selectTab(toolId) { this.setProperties({ selected: toolId, collapsed: false }); }, toggleCollapsed() { this.toggleProperty('collapsed'); } } }); ================================================ FILE: portiaui/app/components/tool-panel.js ================================================ import Ember from 'ember'; import {computedPropertiesEqual} from '../utils/computed'; export default Ember.Component.extend({ classNames: ['tool-panel'], classNameBindings: ['active::hide'], active: computedPropertiesEqual('toolId', 'group.selected') }); ================================================ FILE: portiaui/app/components/tool-tab.js ================================================ import Ember from 'ember'; import {computedPropertiesEqual} from '../utils/computed'; export default Ember.Component.extend({ tagName: 'li', classNameBindings: ['active'], active: computedPropertiesEqual('toolId', 'group.selected'), didInsertElement() { if (!this.$().prev().length) { Ember.run.schedule('afterRender', () => { if (!this.get('group.selected')) { this.send('selectTab'); } }); } }, actions: { selectTab() { this.get('group').send('selectTab', this.get('toolId')); } } }); ================================================ FILE: portiaui/app/components/tooltip-container.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '', delay: { show: 500, hide: 0 }, placement: 'top', text: false, tooltipClasses: null, tooltipContainer: false, tooltipFor: false, triggerEvents: 'hover', viewport: { selector: 'body', padding: 0 }, init() { this._super(); this.$tooltipElement = null; }, didInsertElement() { Ember.run.next(this, this.createTooltip); }, willDestroyElement() { Ember.run.next(this, this.destroyTooltip); }, createTooltip() { const selector = this.get('tooltipFor'); const $tooltipElement = this.$tooltipElement = Ember.$(`#${selector}`); $tooltipElement.tooltip({ /* We pass in an existing element as the template. Bootstrap's tooltip code will happily swallow this and insert it into the DOM. Ember will keep this element updated as data changes. */ template: Ember.$(`[data-tooltip-id="${this.elementId}"]`).detach(), // title is checked for truthiness by bootstrap title: true, container: this.get('tooltipContainer'), delay: this.get('delay'), placement: this.get('placement'), trigger: this.get('triggerEvents'), viewport: this.get('viewport') }); }, destroyTooltip() { this.$tooltipElement.tooltip('destroy'); this.$tooltipElement = null; }, toggleChanged: Ember.observer('toggleTooltip', function() { const e = this.$tooltipElement; if (e) { const action = this.get('toggleTooltip') ? 'show' : 'hide'; e.tooltip(action); } }) }); ================================================ FILE: portiaui/app/components/tooltip-icon.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ tagName: '', actions: { onClick() { const action = this.get('onClick'); if (action) { action(); } } } }); ================================================ FILE: portiaui/app/components/tree-list-item-row.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ classNames: ['tree-list-item-row'], mouseEnter() { if (this.attrs.onMouseEnter && this.attrs.onMouseEnter.call) { this.attrs.onMouseEnter(...arguments); } }, mouseLeave() { if (this.attrs.onMouseLeave && this.attrs.onMouseLeave.call) { this.attrs.onMouseLeave(...arguments); } } }); ================================================ FILE: portiaui/app/components/tree-list-item.js ================================================ import AnimationContainer from './animation-container'; export default AnimationContainer.extend({ tagName: 'li', classNames: ['tree-list-item'], setWidth: false, isCentered: false, hasChildren: false }); ================================================ FILE: portiaui/app/components/tree-list.js ================================================ import Ember from 'ember'; import AnimationContainer from './animation-container'; export default AnimationContainer.extend({ tagName: 'div', classNames: ['tree-list'], reorderable: false, classNameBindings: ['reorderable:reorderable-list'], setWidth: false, drop: function(event) { if(this.get('reorderable')){ event.preventDefault(); this.$('.drop-helper').remove(); var $moved = this.$('.dragging'); var [target, after] = this.getDropTarget(event.originalEvent); // All this are no-ops if(after && (target === $moved.prev()[0]) || !after && (target === $moved.next()[0]) || target === $moved[0]) { return; } var originalIndex = $moved.prevAll().length; var newIndex = Ember.$(target).prevAll().length + (after?1:0); if(Ember.$(target).prevAll().filter($moved).length) { // If dropping after the original position, remove one to // compensate for the removed element newIndex -= 1; } this.sendAction('reorder', originalIndex, newIndex); } }, dragLeave: function(event) { if(this.get('reorderable')) { event.preventDefault(); this.$('.drop-helper').remove(); } }, getDropTarget: function(event){ var container = this.$()[0]; if(event.target === container){ return [null, null]; } var lastParent = Ember.$(event.target).parentsUntil(this.$()).get(-1); var overTarget = event.target.parentNode === container ? event.target: lastParent; var clientRect = overTarget.getBoundingClientRect(); var targetY = event.clientY - clientRect.top; var after = targetY > clientRect.height/2; return [overTarget, after]; }, dragOver: function(event) { if(this.get('reorderable')) { this.$('.drop-helper').remove(); var [target, after] = this.getDropTarget(event.originalEvent); if(target){ event.preventDefault(); var helper = Ember.$('
').addClass('drop-helper'); helper[after?'insertAfter':'insertBefore'](target); } } }, }); ================================================ FILE: portiaui/app/components/url-bar.js ================================================ import Ember from 'ember'; export default Ember.Component.extend({ browser: Ember.inject.service(), tagName: 'form', autofocus: false, backDisabled: Ember.computed.or('disabled', 'noBackUrl'), disabled: Ember.computed.readOnly('browser.disabled'), forwardDisabled: Ember.computed.or('disabled', 'noForwardUrl'), loading: Ember.computed.readOnly('browser.loading'), mode: Ember.computed.readOnly('browser.mode'), noBackUrl: Ember.computed.equal('browser.backBuffer.length', 0), noForwardUrl: Ember.computed.equal('browser.forwardBuffer.length', 0), url: Ember.computed.reads('browser.url'), updateUrl: Ember.observer('browser.url', function() { this.set('url', this.get('browser.url')); }), submit($event) { // ignore form's submit event; $event.stopPropagation(); $event.preventDefault(); }, actions: { back() { if (!this.get('disabled')) { this.get('browser').back(); } }, forward() { if (!this.get('disabled')) { this.get('browser').forward(); } }, submit(url) { if (!this.get('disabled')) { this.setProperties({ 'browser.url': url, 'browser.baseurl': null }); } } } }); ================================================ FILE: portiaui/app/controllers/.gitkeep ================================================ ================================================ FILE: portiaui/app/controllers/projects/project/conflicts/conflict.js ================================================ import Ember from 'ember'; import { isObject, isArray } from '../../../../utils/types'; function isConflict(obj) { return isObject(obj) && '__CONFLICT' in obj; } /** * Sort keys so that indexes in the same array are in descending order. * This is the correct order in that patches can be unambiguously applied * sortKeys([['a', '1'], ['a', '10'], ['a', '2']]) => [['a', '10'], ['a', '2'], ['a', '1']] */ function sortKeys(keys){ return keys.sort(function(a,b){ if(a.length === b.length) { for (var i = 0, len = a.length; i < len; i++) { if(a[i] !== b[i]) { if(/^\d+$/.test(a[i] + b[i])) { return parseInt(b[i]) - parseInt(a[i]); } else { return a[i] > b[i] ? -1 : 1; } } } } else { return a.length > b.length ? -1 : 1; } }); } /** * Apply a set of patches in the format {'object.path': new_value} */ function applyPatches(obj, values) { var keys = sortKeys(Object.keys(values).map(key => key.split('.'))); for(var key of keys) { patch(obj, key, values[key.join('.')]); } return obj; } /** * Set object's specified path to value */ function patch(obj, path, value) { if(isArray(obj)) { var idx = parseInt(path[0]) + 1; for (var i = 0, len = obj.length; i < len; i++) { if(isConflict(obj[i])) { idx--; if(idx === 0) { obj.splice(i, 1, ...value); return; } } } } else if (isObject(obj)) { if(path.length === 1) { obj[path] = value; } else { patch(obj[path[0]], path.slice(1), value); } return; } throw new Error("Could not patch object"); } export default Ember.Controller.extend({ projectController: Ember.inject.controller('projects.project'), init: function(){ this.set('pendingPaths', []); this.set('resolvedValues', {}); // This is saved in flat format {'a.b.c.0': value} this._super(); }, getResolvedTree: function(){ var content = this.get('model.contents'); // JSON parse + stringify to deep copy because neither // Ember.copy or $.extend({}, true) worked content = JSON.parse(JSON.stringify(content)); applyPatches(content, this.get('resolvedValues')); return content; }, haveConflicts: Ember.computed('pendingPaths.[]', function(){ return this.get('pendingPaths').length > 0; }), actions: { updateConflict: function(path, resolved, value) { if(resolved) { this.get('pendingPaths').removeObject(path); this.get('resolvedValues')[path] = value; } else if (!this.get('pendingPaths').contains(path)) { this.get('pendingPaths').pushObject(path); } }, saveFile: function(){ var project = this.get('projectController.model.id'); var fileName = this.get('model.file'); var content = this.getResolvedTree(); var url = '/projects/' + project + '/spec/' + fileName.replace(/\.json$/, ''); $.post(url, JSON.stringify(content)).then(() => { this.transitionTo('projects.project.conflicts'); }); } } }); ================================================ FILE: portiaui/app/controllers/projects/project/conflicts.js ================================================ import Ember from 'ember'; export default Ember.Controller.extend({ projectController: Ember.inject.controller('projects.project'), currentFileName: null, conflictedKeyPaths: {}, conflictedFiles: Ember.computed('model', function() { return Object.keys(this.get('model')).sort().map((name) => ({ name: name, encodedName: btoa(name), })); }), }); ================================================ FILE: portiaui/app/controllers/projects/project/schema/field/options.js ================================================ import Ember from 'ember'; export default Ember.Controller.extend({ actions: { closeOptions() { this.send('close'); } } }); ================================================ FILE: portiaui/app/controllers/projects/project/spider/link-options.js ================================================ import Ember from 'ember'; export default Ember.Controller.extend({ actions: { closeOptions() { this.send('close'); } } }); ================================================ FILE: portiaui/app/controllers/projects/project/spider/options.js ================================================ import Ember from 'ember'; export default Ember.Controller.extend({ actions: { closeOptions() { this.send('close'); } } }); ================================================ FILE: portiaui/app/controllers/projects/project/spider/sample/data/annotation/options.js ================================================ import Ember from 'ember'; export default Ember.Controller.extend({ actions: { closeOptions() { this.send('close'); } } }); ================================================ FILE: portiaui/app/controllers/projects/project/spider/sample/data.js ================================================ import Ember from 'ember'; import { task, timeout } from 'ember-concurrency'; import {getColors} from '../../../../../utils/colors'; import {BaseSelectorGenerator, elementPath} from '../../../../../utils/selectors'; export default Ember.Controller.extend({ browser: Ember.inject.service(), dispatcher: Ember.inject.service(), uiState: Ember.inject.service(), selectionModeIcons: { select: 'tool-select', add: 'tool-add', remove: 'tool-remove', edit: 'tool-multiple' }, selectionModeText: { select: 'Select an existing annotation', add: 'Add a new annotation', remove: 'Remove an annotation', edit: 'Add/remove extra elements from an existing annotation' }, selectionModeIds: { select: 'tool-select-button', add: 'tool-add-button', remove: 'tool-remove-button', edit: 'tool-multiple-button' }, cssEnabled: Ember.computed.readOnly('browser.cssEnabled'), magicToolActive: Ember.computed.alias('uiState.selectedTools.magicToolActive'), hoveredElement: Ember.computed.readOnly('uiState.viewPort.hoveredElement'), originalSelectedElement: Ember.computed.alias('uiState.viewPort.originalSelectedElement'), sample: Ember.computed.readOnly('model'), selectedModel: Ember.computed.alias('uiState.viewPort.selectedModel'), selectionMode: Ember.computed.alias('uiState.selectedTools.selectionMode'), hoveredModels: Ember.computed( 'uiState.viewPort.hoveredModels', 'hoveredElement', 'sample.dataStructure.annotations', { get(key) { const hoveredModels = this.get('uiState.viewPort.hoveredModels'); if (hoveredModels !== this._hoveredModels) { return this.set(key, hoveredModels); } const hoveredElement = this.get('hoveredElement'); let models; if (hoveredElement) { const annotations = this.get('sample.dataStructure.annotations'); models = annotations && annotations.get(Ember.guidFor(hoveredElement)); } models = (models || []).filterBy('constructor.modelName', 'annotation'); return this.set(key, models); }, set(key, value) { this._hoveredModels = value; return this.set('uiState.viewPort.hoveredModels', value); } }), selectedModelElements: Ember.computed('selectedModel.elements', function() { return this.get('selectedModel.elements') || []; }), selectedElement: Ember.computed( 'uiState.viewPort.selectedElement', 'selectedModelElements.[]', { get() { const selectedElement = this.get('uiState.viewPort.selectedElement'); const selectedModelElements = this.get('selectedModelElements'); if (selectedElement && selectedModelElements.includes(selectedElement)) { return selectedElement; } return this.set('selectedElement', selectedModelElements[0]); }, set(key, value) { return this.set('uiState.viewPort.selectedElement', value); } }), activeSelectionMode: Ember.computed( 'selectionMode', 'magicToolActive', 'hoveredElement', 'hoveredModels.[]', 'selectedElement', 'selectedModel', 'selectedModelElements.length', 'generalizableModel', function() { const selectedMode = this.get('selectionMode'); const magicToolActive = this.get('magicToolActive'); if (selectedMode) { return selectedMode; } else if (magicToolActive) { const hoveredElement = this.get('hoveredElement'); const hoveredModels = this.getWithDefault('hoveredModels', []); const selectedModel = this.get('selectedModel'); if (hoveredModels.length) { if (hoveredModels.includes(selectedModel)) { if (this.get('selectedModelElements.length') === 1) { return 'remove'; } return 'edit'; } else { return 'select'; } } else if (hoveredElement) { if (this.get('generalizableModel') || (selectedModel && this.get('selectedModelElements.length') === 0)) { return 'edit'; } return 'add'; } return 'select'; } }), annotationColors: Ember.computed( 'sample.orderedAnnotations.length', 'activeSelectionMode', 'hoveredElement', function() { const annotations = this.getWithDefault('sample.orderedAnnotations.length', 0); if (this.get('activeSelectionMode') === 'add' && this.get('hoveredElement')) { return getColors(annotations + 1); } if (annotations) { return getColors(annotations); } return []; }), generalizableModel: Ember.computed( 'selectionMode', 'selectedModel', 'hoveredElement', 'sample.orderedChildren.@each.elements', function() { const isEditMode = this.get('selectionMode') === 'edit'; const selectedModel = this.get('selectedModel'); const hoveredElement = this.get('hoveredElement'); if (!hoveredElement) { return; } // if user has manually chosen the edit tool, and selected an annotation, use that ... if (selectedModel && isEditMode) { return selectedModel; } // ... otherwise find best match const annotations = this.get('sample.orderedAnnotations'); if (annotations.length) { const annotationsToMatch = annotations.slice(); // if an annotation is selected prefer it // add it to the start of the list, sorting preserves order if (selectedModel) { annotationsToMatch.removeObject(selectedModel); annotationsToMatch.unshift(selectedModel); } const hoveredElementPath = elementPath(hoveredElement); const possibilities = annotationsToMatch.map(annotation => { const selectorGenerator = BaseSelectorGenerator.create({ elements: annotation.get('elements') }); let distance = selectorGenerator.generalizationDistance(hoveredElement); if (distance < Infinity && !isEditMode) { // reject annotations with elements that share a container with the // hovered element const annotationPaths = annotation.get('elements').map(elementPath); const containerElements = annotation.get('parent.elements'); container: for (let containerElement of containerElements) { const containerPath = elementPath(containerElement); const depth = containerPath.length - 1; for (let annotationPath of annotationPaths) { if (containerElement === annotationPath[depth] && containerElement === hoveredElementPath[depth]) { distance = Infinity; break container; } } } } return { annotation, distance }; }).sortBy('distance'); const {annotation, distance} = possibilities[0]; // if user has manually chosen the edit tool return the best match, otherwise use // a distance cutoff if (isEditMode || distance < (selectedModel ? 4 : 2)) { return annotation; } } }), hoverOverlayColor: Ember.computed( 'showHoverOverlay', 'annotationColors.length', 'hoveredModels.firstObject.orderedIndex', 'generalizableModel.orderedIndex', 'selectedModel.orderedIndex', 'activeSelectionMode', function() { if (this.get('showHoverOverlay')) { const colors = this.getWithDefault('annotationColors', []); const activeSelectionMode = this.get('activeSelectionMode'); if (activeSelectionMode === 'add') { return colors.get('lastObject'); } else if (activeSelectionMode === 'select' || activeSelectionMode === 'remove') { return colors[this.get('hoveredModels.firstObject.orderedIndex')]; } else if (activeSelectionMode === 'edit') { return colors[this.get('generalizableModel.orderedIndex')] || colors[this.get('selectedModel.orderedIndex')]; } } }), showHoverOverlay: Ember.computed( 'hoveredElement', 'hoveredModels.[]', 'generalizableModel', 'selectedModel', 'activeSelectionMode', function() { const activeSelectionMode = this.get('activeSelectionMode'); const hoveredElement = this.get('hoveredElement'); const hoveredModels = this.get('hoveredModels'); if (hoveredElement) { if (activeSelectionMode === 'add') { return true; } else if ((activeSelectionMode === 'select' || activeSelectionMode === 'remove') && hoveredModels.length) { return true; } else if (activeSelectionMode === 'edit' && (this.get('generalizableModel') || this.get('selectedModel'))) { return true; } } return false; }), _selectElement: task(function * () { yield timeout(1000); const dispatcher = this.get('dispatcher'); const magicToolActive = this.get('magicToolActive'); const selectionMode = this.get('activeSelectionMode'); const hoveredElement = this.get('hoveredElement'); const hoveredModels = this.get('hoveredModels'); const selectedModel = this.get('selectedModel'); switch (selectionMode) { case 'select': if (hoveredModels.length) { const model = hoveredModels[0]; dispatcher.selectAnnotationElement( model, hoveredElement, /* redirect = */true); } else { dispatcher.clearSelection(); } break; case 'add': if (hoveredElement) { dispatcher.addAnnotation( /* auto item */null, hoveredElement, undefined, /* redirect = */true); } else { dispatcher.clearSelection(); } break; case 'remove': const annotation = this.get('uiState.models.annotation'); const field = annotation.get('field.content'); annotation.set('field', field); annotation.save().then(() => { if (selectedModel) { dispatcher.removeAnnotation(selectedModel); } else if (hoveredModels.length) { dispatcher.removeAnnotation(hoveredModels[0]); } else { dispatcher.clearSelection(); } }); break; case 'edit': const matchingModel = this.get('generalizableModel') || selectedModel; if (!hoveredElement) { dispatcher.clearSelection(); } else if (matchingModel && !hoveredModels.includes(matchingModel)) { dispatcher.addElementToAnnotation(matchingModel, hoveredElement); } else if (hoveredModels.length) { let model; if (selectedModel) { model = selectedModel; } else { model = hoveredModels.find(model => (model.get('elements') || []).length > 1) || hoveredModels[0]; } dispatcher.removeElementFromAnnotation(model, hoveredElement); } break; } if (magicToolActive) { this.set('selectionMode', null); } }).drop(), actions: { toggleCSS() { const browser = this.get('browser'); if (this.get('cssEnabled')) { browser.disableCSS(); } else { browser.enableCSS(); } }, toggleMagicTool() { const magicToolActive = this.get('magicToolActive'); const selectionMode = this.get('selectionMode'); if (magicToolActive) { this.set('magicToolActive', false); if (!selectionMode) { this.set('selectionMode', 'add'); } } else { this.setProperties({ magicToolActive: true, selectionMode: null }); } }, selectElement() { this.get('_selectElement').perform(); } } }); ================================================ FILE: portiaui/app/controllers/projects/project/spider.js ================================================ import Ember from 'ember'; import { NAMED_COLORS } from '../../../utils/colors'; function filterLinkElements(filterFn) { return Ember.computed('allLinkElements', 'extractedItems.links', function() { const linkElements = this.get('allLinkElements'); const followed = this.getWithDefault('extractedItems.links', {}); const filteredElements = []; for (let element of linkElements) { const url = URI(element.href).fragment('').toString(); if (filterFn(url, followed)) { filteredElements.push(element); } } return filteredElements; }); } function mapOverlayElements(elementsProperty, color) { return Ember.computed.map(elementsProperty, element => ({ guid: Ember.guidFor(element), element, color })); } export default Ember.Controller.extend({ extractedItems: Ember.inject.service(), selectorMatcher: Ember.inject.service(), webSocket: Ember.inject.service(), // only a tags with a non-empty href attribute linkSelector: 'a[href]:not([href=""]):not([href^="javascript:"])', allLinkElements: [], showExtractedItems: Ember.computed.bool('extractedItems.items.length'), followedLinkElements: filterLinkElements(function(url, followed) { return followed[url] === 'raw'; }), jsLinkElements: filterLinkElements(function(url, followed) { return followed[url] === 'js'; }), ignoredLinkElements: filterLinkElements(function(url, followed) { return !followed[url]; }), followedLinkOverlayElements: mapOverlayElements('followedLinkElements', NAMED_COLORS.green), jsLinkOverlayElements: mapOverlayElements('jsLinkElements', NAMED_COLORS.blue), ignoredLinkOverlayElements: mapOverlayElements('ignoredLinkElements', NAMED_COLORS.red), linkOverlayElements: Ember.computed( 'followedLinkOverlayElements', 'jsLinkOverlayElements', 'ignoredLinkOverlayElements', function() { const followed = this.get('followedLinkOverlayElements'); const js = this.get('jsLinkOverlayElements'); const ignored = this.get('ignoredLinkOverlayElements'); return [].concat(followed).concat(js).concat(ignored); }), init() { let ws = this.get('webSocket'); ws.addCommand('metadata', this, this.msgMetadata); ws.addCommand('update_spider', this, this.msgMetadata); }, activate() { this.get('selectorMatcher').register(this.linkSelector, this, this.updateLinkElements); }, deactivate() { this.get('selectorMatcher').unRegister(this.linkSelector, this, this.updateLinkElements); }, updateLinkElements(elements) { this.set('allLinkElements', elements); } }); ================================================ FILE: portiaui/app/controllers/projects/project.js ================================================ import Ember from 'ember'; export default Ember.Controller.extend({ browser: Ember.inject.service(), queryParams: ['url', 'baseurl'], url: Ember.computed.alias('browser.url'), baseurl: Ember.computed.alias('browser.baseurl'), clickHandler: null, setClickHandler(fn) { this.clickHandler = fn; }, clearClickHandler() { this.clickHandler = null; }, actions: { viewPortClick() { if (this.clickHandler) { this.clickHandler(...arguments); } } } }); ================================================ FILE: portiaui/app/helpers/.gitkeep ================================================ ================================================ FILE: portiaui/app/helpers/array-get.js ================================================ import Ember from 'ember'; export default Ember.Helper.extend({ compute(params/*, hash*/) { this.setProperties({ obj: params[0], index: params[1] }); return this.get('content'); }, obj: null, index: null, content: Ember.computed('obj.[]', 'index', function() { return this.get('obj').get(this.get('index')); }), contentDidChange: Ember.observer('content', function () { this.recompute(); }) }); ================================================ FILE: portiaui/app/helpers/attribute-annotation.js ================================================ import Ember from 'ember'; export default Ember.Helper.extend({ compute([annotations, attribute]) { this.setProperties({ annotations, attribute }); return this.get('content'); }, annotations: null, attribute: null, content: Ember.computed('annotations.[]', 'attribute', function() { const attribute = this.get('attribute'); return this.getWithDefault('annotations', []).find(annotation => annotation.getWithDefault('attribute', null) === attribute) || {}; }), contentDidChange: Ember.observer('content', function () { this.recompute(); }) }); ================================================ FILE: portiaui/app/helpers/chain-actions.js ================================================ import Ember from 'ember'; export function chainActions(params/*, hash*/) { return function() { for (let action of params) { if (action.call) { action(); } } }; } export default Ember.Helper.helper(chainActions); ================================================ FILE: portiaui/app/helpers/guid.js ================================================ import Ember from 'ember'; export function guid([obj]/*, hash*/) { return Ember.guidFor(obj); } export default Ember.Helper.helper(guid); ================================================ FILE: portiaui/app/helpers/includes.js ================================================ import Ember from 'ember'; export function includes([list, value]) { return list && list.includes && list.includes(value); } export default Ember.Helper.helper(includes); ================================================ FILE: portiaui/app/helpers/indexed-object.js ================================================ import Ember from 'ember'; export function indexedObject([ param ] /*, hash*/) { let indexed = {}, i = 0; for (let key of Object.keys(param)) { indexed[key] = { index: i, value: param[key] }; i += 1; } return indexed; } export default Ember.Helper.helper(indexedObject); ================================================ FILE: portiaui/app/helpers/is-empty-object.js ================================================ import Ember from 'ember'; import {isObject} from './is-object'; export function isEmptyObject(params) { return isObject(params) && !Object.keys(...params).length; } export default Ember.Helper.helper(isEmptyObject); ================================================ FILE: portiaui/app/helpers/is-object-or-array.js ================================================ import Ember from 'ember'; import { isArrayHelper } from 'ember-truth-helpers/helpers/is-array'; import { isObject } from './is-object'; export function isObjectOrArray(params) { return isObject(params) || isArrayHelper(params); } export default Ember.Helper.helper(isObjectOrArray); ================================================ FILE: portiaui/app/helpers/is-object.js ================================================ import Ember from 'ember'; import { toType } from '../utils/types'; export function isObject([object]) { return toType(object) === 'object'; } export default Ember.Helper.helper(isObject); ================================================ FILE: portiaui/app/index.html ================================================ Portia {{content-for "head"}} {{content-for "head-footer"}} {{content-for "body"}} {{content-for "body-footer"}} ================================================ FILE: portiaui/app/initializers/ui-state.js ================================================ export function initialize(application) { application.inject('service:ui-state', 'router', 'router:main'); application.inject('service:ui-state', 'projectRoute', 'route:projects/project'); application.inject('service:ui-state', 'spiderRoute', 'route:projects/project/spider'); application.inject('service:ui-state', 'sampleRoute', 'route:projects/project/spider/sample'); application.inject('service:ui-state', 'dataRoute', 'route:projects/project/spider/sample/data'); application.inject('service:ui-state', 'itemRoute', 'route:projects/project/spider/sample/data/item'); application.inject('service:ui-state', 'annotationRoute', 'route:projects/project/spider/sample/data/annotation'); application.inject('service:ui-state', 'schemaRoute', 'route:projects/project/schema'); application.inject('service:ui-state', 'fieldRoute', 'route:projects/project/schema/field'); } export default { name: 'ui-state', initialize: initialize }; ================================================ FILE: portiaui/app/instance-initializers/error-handler.js ================================================ import Ember from 'ember'; import DS from 'ember-data'; function logErrorStack(e, level) { let text = e.toString(); let stack = e.stack; if (stack) { if (!stack.startsWith(text)) { stack = `${text}\n${stack}`; } text = stack; } if (!level){ Ember.Logger.warn(text); } else { level(text); } } export function initialize(applicationInstance) { const notificationManager = applicationInstance.lookup('service:notification-manager'); var loggedErrors = new Set(); function notifyError(err) { let logged = false; if (window.NREUM) { window.NREUM.noticeError(err); logged = true; } if (window.Raven) { window.Raven.captureException(err); logged = true; } const instructions = logged ? "Our developers have already been notified." : "Please notify the developers. Details have been logged to the console."; let isDeleted = err => ( err.message && (/event `(didSetProperty|deleteRecord)`.*in state root\./.test(err.message) || /calling set on destroyed object/.test(err.message)) ); if (err instanceof DS.AdapterError) { for (let error of err.errors) { if (error.id && loggedErrors.has(error.id)) { continue; } Ember.Logger.warn(`AdapterError: ${error.title}\n${error.detail}`); notificationManager.add({ title: error.title || 'Server error', message: 'An error occurred while communicating with the server. ' + error.status >= 500 ? instructions : error.detail, type: +error.status >= 500 ? 'danger' : 'warning' }); if (error.id) { loggedErrors.add(error.id); } } } else if (isDeleted(err)) { // Skip errors when operating on deleted Ember.Logger.debug(`Model Error: ${err.message}`); logErrorStack(err, Ember.Logger.debug); } else if (err.fileName === 'websocket-browser-load') { logErrorStack(err, Ember.Logger.debug); } else { logErrorStack(err); notificationManager.add({ title: err.title || 'Unexpected error', message: 'An unexpected error has occurred. ' + instructions, type: 'danger' }); } } Ember.onerror = notifyError; } export default { name: 'error-handler', initialize: initialize }; ================================================ FILE: portiaui/app/mixins/options-route.js ================================================ import Ember from 'ember'; export default Ember.Mixin.create({ uiState: Ember.inject.service(), activate() { this.set('uiState.slideMain', true); }, deactivate() { this.set('uiState.slideMain', false); } }); ================================================ FILE: portiaui/app/mixins/save-spider-mixin.js ================================================ import Ember from 'ember'; export default Ember.Mixin.create({ webSocket: Ember.inject.service(), saveSpider() { let savePromise = this.get('spider').save(); savePromise.then(() => this.get('webSocket').send({ 'spider': this.get('spider.id'), 'project': this.get('spider.project.id'), '_command': 'update_spider' }) ); return savePromise; } }); ================================================ FILE: portiaui/app/models/.gitkeep ================================================ ================================================ FILE: portiaui/app/models/annotation.js ================================================ import Ember from 'ember'; import DS from 'ember-data'; import BaseAnnotation from './base-annotation'; import { elementPath, smartSelector } from '../utils/selectors'; export default BaseAnnotation.extend({ attribute: DS.attr('string', { defaultValue: 'content' }), text_content: DS.attr('string', { defaultValue: 'content' }), required: DS.attr('boolean', { defaultValue: false }), repeated: DS.attr('boolean', { defaultValue: false }), selectionMode: DS.attr('string', { defaultValue: 'auto' }), selector: DS.attr('string'), xpath: DS.attr('string'), acceptSelectors: DS.attr('array', { defaultValue() { return []; } }), rejectSelectors: DS.attr('array', { defaultValue() { return []; } }), preText: DS.attr('string'), postText: DS.attr('string'), field: DS.belongsTo(), extractors: DS.hasMany(), name: Ember.computed.readOnly('field.name'), type: Ember.computed.readOnly('field.type'), ownerSample: Ember.computed.readOnly('parent.ownerSample'), orderedIndex: Ember.computed('ownerSample.orderedAnnotations', function() { return (this.get('ownerSample.orderedAnnotations') || []).indexOf(this); }), addElement(element) { this.moveElement(element, 'acceptSelectors', 'rejectSelectors'); }, removeElement(element) { this.moveElement(element, 'rejectSelectors', 'acceptSelectors'); }, moveElement(element, toProperty, fromProperty) { const toSelectors = this.get(toProperty); const fromSelectors = this.get(fromProperty); const path = elementPath(element); const root = path[0]; const selector = smartSelector(element); const addSelectors = []; const removeSelectors = []; // a selector may match more than one element, we only want to remove the single element for (let fromSelector of fromSelectors) { const elements = Array.from(root.querySelectorAll(fromSelector)); if (elements.includes(element)) { removeSelectors.addObject(fromSelector); elements.removeObject(element); for (let addElement of elements) { addSelectors.addObject(smartSelector(addElement)); } } } fromSelectors.removeObjects(removeSelectors); fromSelectors.addObjects(addSelectors); toSelectors.addObject(selector); }, setSelector(selector) { this.setProperties({ acceptSelectors: selector ? [selector] : [], rejectSelectors: [] }); } }); ================================================ FILE: portiaui/app/models/base-annotation.js ================================================ import { belongsTo } from 'ember-data/relationships'; import BaseModel from './base'; export default BaseModel.extend({ parent: belongsTo('item', { inverse: 'annotations' }) }); ================================================ FILE: portiaui/app/models/base.js ================================================ import Ember from 'ember'; import DS from 'ember-data'; import EmptyObject from "ember-data/-private/system/empty-object"; const { get } = Ember; let currentActionModel = null; const modelActionQueue = []; function runActions() { if (currentActionModel && currentActionModel.get('isSaving')) { // current action has not finished return; } currentActionModel = null; while (modelActionQueue.length) { const nextModel = modelActionQueue.shift(); if (nextModel.get('isSaving')) { // model has started saving again, wait for the next didCommit event return; } if (nextModel.get('isDeleted') && !nextModel.get('hasDirtyAttributes')) { // model has been deleted continue; } if (nextModel.get('pendingDelete')) { nextModel.deleteRecord(); nextModel.set('pendingDelete', false); } const pendingSave = nextModel.get('pendingSave'); if (pendingSave) { nextModel.set('pendingSave', null); const {resolver, options} = pendingSave; // apply the save and resolve the promise, then wait for the next didCommit event nextModel.save(options).then(resolver.resolve, resolver.reject); return; } } } function mergeSaveOptions(dst, src) { if (!dst) { return src; } src = src || {}; if (src.coalesce) { if (dst.coalesce) { for (let coalesce of src.coalesce) { const {model, options} = coalesce; const matchingCoalesce = dst.coalesce.findBy('model', model); if (matchingCoalesce) { matchingCoalesce.options = mergeSaveOptions(matchingCoalesce.options, options); } else { dst.coalesce.push(coalesce); } } } else { dst.coalesce = src.coalesce; } } if (src.partial) { if (dst.partial) { for (let field of src.partial) { if (!dst.partial.includes(field)) { dst.partial.push(field); } } } // else dst is a full save, keep it that way } else if (dst.partial) { delete dst.partial; } return dst; } export default DS.Model.extend({ pendingDelete: false, pendingSave: null, isDeleted: Ember.computed('currentState', 'pendingDelete', function() { return get(this._internalModel.currentState, 'isDeleted') || this.get('pendingDelete'); }).readOnly(), save(options) { const isSaving = currentActionModel && currentActionModel.get('isSaving'); const isExtra = options && options.adapterOptions && options.adapterOptions.coalesce && options.adapterOptions.coalesce.type === 'extra'; if (isSaving && !isExtra) { // allow coalesced requests through since we're inside the main save call let pendingSave = this.get('pendingSave'); if (pendingSave) { pendingSave.options = mergeSaveOptions(pendingSave.options, options); } else { pendingSave = { resolver: Ember.RSVP.defer(), options: options }; this.set('pendingSave', pendingSave); modelActionQueue.push(this); } return pendingSave.resolver.promise; } currentActionModel = this; /* bulk saving helper using the coalesce option. this will generate the correct adapterOptions for the adapter to coalesce the requests: model.save({ coalesce: [{ model: otherModel1, options: { partial: ['name'] } }, { model: otherModel2 }] }); */ const coalescePromises = []; if (options && options.coalesce) { // a shared list for the adapter to track coalesced updates. const sharedUpdates = []; if (!options.adapterOptions) { options.adapterOptions = {}; } options.adapterOptions.coalesce = { type: 'main', updates: sharedUpdates }; for (let {model, options: modelOptions} of options.coalesce) { const record = model._internalModel; if (get(record, 'currentState.stateName') === 'root.deleted.saved' || record.isDeleted()) { throw new Ember.Error( "You can not pass deleted models in the coalesce options to the " + "save method."); } else if (record.isNew()) { throw new Ember.Error( "You can not pass unsaved models in the coalesce options to the " + "save method."); } // create a new request for each updated model. the adapter will // coalesce requests with the same value of coalesce.updates. // the request with a coalesce.type of 'main' MUST come after // those type 'extra'. const modelPromise = model.save(Ember.assign({}, modelOptions, { // settings adapterOptions directly so we don't trigger // this code path again. adapterOptions: { coalesce: { type: 'extra', updates: sharedUpdates } } })); coalescePromises.push(modelPromise); } } /* partial updates using the partial option. this will pass the partial option to the serializer through adapterOptions, so only the selected fields will be serialized and sent in the request. we also need to track the internalModel._inFlightAttributes correctly. model.save({ partial: ['name', 'age'] }); */ const internalModel = this._internalModel; let originalAttributes = internalModel._attributes; if (options && options.partial) { if (!options.adapterOptions) { options.adapterOptions = {}; } options.adapterOptions.partial = options.partial; // prepare _attributes for flushChangedAttributes call in // store.scheduleSave, so that only the attributes selected for // partial save are marked as inFlight. internalModel._attributes = new EmptyObject(); for (let key of options.partial) { if (key in originalAttributes) { internalModel._attributes[key] = originalAttributes[key]; delete originalAttributes[key]; } } } const mainPromise = this._super(options); if (options && options.partial) { internalModel._attributes = originalAttributes; } coalescePromises.unshift(mainPromise); // resolve the .save() promise when all coalesced have been resolved return Ember.RSVP.allSettled(coalescePromises).then(() => mainPromise); }, deleteRecord() { if (this.get('isSaving')) { this.set('pendingDelete', true); } return this._super(...arguments); }, reload() { if (this.get('isSaving')) { // record is inFlight, so wait for the request to finish and return // this instance return DS.PromiseObject.create({ promise: Ember.RSVP.Promise((resolve, reject) => { this.one('didCommit', () => { resolve(this); resolve = reject = Ember.K; }); this.one('becameInvalid', () => { resolve(this); resolve = reject = Ember.K; }); this.one('becameError', Ember.run.next, () => { reject(this.get('adapterError')); resolve = reject = Ember.K; }); }) }); } return this._super(...arguments); }, set(key) { this._clearPendingDelete(key); this._super(...arguments); }, setProperties(hash) { this._clearPendingDelete(...Object.keys(hash)); this._super(...arguments); }, runActions: Ember.on('didCommit', function() { // run in the next run loop so that any other events that may modify // the state of the instance have a chance to run first. if (currentActionModel === this) { currentActionModel = null; Ember.run.next(Ember.run.once, runActions); } }), clearPendingAndRunActions: Ember.on('becameError', 'becameInvalid', function() { this.setProperties({ pendingDelete: false, pendingSave: null, }); this.runActions(); }), _clearPendingDelete(...keys) { if (this.get('pendingDelete')) { for (let key of keys) { if (!['pendingDelete', 'pendingSave'].includes(key)) { // just to be safe cancel the delete so we don't lose data this.set('pendingDelete', false); break; } } } } }); ================================================ FILE: portiaui/app/models/extractor.js ================================================ import DS from 'ember-data'; import BaseModel from './base'; export default BaseModel.extend({ type: DS.attr('string'), value: DS.attr('string'), project: DS.belongsTo(), annotations: DS.hasMany() }); ================================================ FILE: portiaui/app/models/field.js ================================================ import DS from 'ember-data'; import BaseModel from './base'; export const FIELD_TYPES = [ 'date', 'geopoint', 'image', 'number', 'price', 'raw html', 'safe html', 'text', 'url']; export default BaseModel.extend({ name: DS.attr('string'), type: DS.attr('string'), required: DS.attr('boolean'), vary: DS.attr('boolean'), schema: DS.belongsTo({ async: true }), annotations: DS.hasMany({ async: true }) }); ================================================ FILE: portiaui/app/models/item.js ================================================ import Ember from 'ember'; import DS from 'ember-data'; import BaseAnnotation from './base-annotation'; export default BaseAnnotation.extend({ name: DS.attr('string'), selector: DS.attr('string'), repeatedSelector: DS.attr('string'), siblings: DS.attr('number', { defaultValue: 0 }), sample: DS.belongsTo(), schema: DS.belongsTo(), annotations: DS.hasMany('base-annotation', { inverse: 'parent', polymorphic: true }), ownerSample: Ember.computed(function() { return DS.PromiseObject.create({ promise: this.get('sample').then(sample => sample || this.get('parent.ownerSample')) }); }), orderedAnnotations: Ember.computed( 'annotations', 'annotations.@each.orderedAnnotations', function() { return [].concat(...this.get('annotations').map(annotation => ( annotation.constructor.modelName === 'item' ? annotation.getWithDefault('orderedAnnotations', []) : [annotation] ))); }), orderedChildren: Ember.computed( 'annotations.[]', 'annotations.@each.orderedChildren', function() { return [].concat(...this.get('annotations').map(annotation => ( [annotation].concat( annotation.constructor.modelName === 'item' ? annotation.getWithDefault('orderedChildren', []) : [] ) ))); }), depth: Ember.computed('parent.depth', function() { let parentDepth = this.get('parent.depth'); return (parentDepth || 0) + 1; }) }); ================================================ FILE: portiaui/app/models/project.js ================================================ import Ember from 'ember'; import DS from 'ember-data'; import BaseModel from './base'; import { memberAction } from 'ember-api-actions'; const { inject: { service } } = Ember; function memberActionAndMarkClean(options) { const method = memberAction(options); return function(payload) { return method.call(this, payload).then(result => { this.markClean(); return result; }); }; } const Project = BaseModel.extend({ changes: service(), name: DS.attr('string'), spiders: DS.hasMany(), schemas: DS.hasMany(), extractors: DS.hasMany(), status: memberAction({path: 'status', type: 'GET'}), deploy: memberAction({path: 'deploy', type: 'POST'}), publish: memberActionAndMarkClean({path: 'publish'}), copy: memberActionAndMarkClean({path: 'copy', type: 'POST'}), reset: memberActionAndMarkClean({path: 'reset'}), markClean() { this.set('changes.hasChanges', false); } }); export default Project; ================================================ FILE: portiaui/app/models/sample.js ================================================ import Ember from 'ember'; import DS from 'ember-data'; import BaseModel from './base'; const Sample = BaseModel.extend({ name: DS.attr('string'), url: DS.attr('string'), spider: DS.belongsTo(), items: DS.hasMany(), body: DS.attr('string', { default: 'original_body' }), orderedAnnotations: Ember.computed('items.content.@each.orderedAnnotations', function() { return [].concat(...this.get('items').mapBy('orderedAnnotations')); }), orderedChildren: Ember.computed('items.content.@each.orderedChildren', function() { return [].concat(...this.get('items').map(item => [item].concat( item.getWithDefault('orderedChildren', [])))); }) }); Sample.reopenClass({ normalizeTitle(title) { return title .trim() .replace(/[^a-z\s_-]/ig, '') .substring(0, 48) .trim() .replace(/\s+/g, ' '); } }); export default Sample; ================================================ FILE: portiaui/app/models/schema.js ================================================ import DS from 'ember-data'; import BaseModel from './base'; export default BaseModel.extend({ name: DS.attr('string'), default: DS.attr('boolean'), project: DS.belongsTo(), fields: DS.hasMany(), items: DS.hasMany() }); ================================================ FILE: portiaui/app/models/spider.js ================================================ import Ember from 'ember'; import DS from 'ember-data'; import BaseModel from './base'; export default BaseModel.extend({ name: DS.attr('string'), nameAlias: Ember.computed('id', 'name', { get() { return this.get('name') || this.get('id'); }, set(key, value) { this.set('name', value); return value; } }), startUrls: DS.attr('startUrl', { defaultValue() { return []; } }), respectNofollow: DS.attr('boolean'), pageActions: DS.attr('array', { defaultValue() { return []; } }), project: DS.belongsTo(), // login performLogin: DS.attr('boolean'), loginUrl: DS.attr('string'), loginUser: DS.attr('string'), loginPassword: DS.attr('string'), // links linksToFollow: DS.attr('string', { defaultValue: 'all' }), followPatterns: DS.attr('array', { defaultValue() { return []; } }), excludePatterns: DS.attr('array', { defaultValue() { return []; } }), // move to ui state? showLinks: DS.attr('boolean'), respectNoFollow: DS.attr('boolean', { defaultValue: true }), // JS jsEnabled: DS.attr('boolean'), jsEnablePatterns: DS.attr('array', { defaultValue() { return []; } }), jsDisablePatterns: DS.attr('array', { defaultValue() { return []; } }), samples: DS.hasMany({ async: true }), firstUrl: Ember.computed('startUrls.firstObject', function() { const urls = this.get('startUrls').filterBy('type', 'url'); return (urls.length !== 0) ? urls[0].url : undefined; }) }); ================================================ FILE: portiaui/app/models/start-url.js ================================================ import Ember from 'ember'; import { flatten } from '../utils/utils'; import { augmentFragmentList, fragmentToString } from '../utils/start-urls'; const StartUrl = Ember.Object.extend({ type: 'url', isGenerated: false, optionsTitle: '', componentName: 'project-structure-spider-url', show() { return this.get('url'); }, serialize() { const serialized = { 'url': this.show(), 'type': this.get('type') }; return this.addSerialized(serialized); }, addSerialized(serialized) { return serialized; }, save(spider) { spider.get('startUrls').pushObject(this); spider.save(); return this; } }); const GeneratedUrl = StartUrl.extend({ type: 'generated', isGenerated: true, optionsTitle: 'URL Generation', componentName: 'project-structure-spider-generated-url', optionsComponentName: 'generated-url-options', init() { const defaultFragments = [ { type: 'fixed', value: this.get('url') } ]; const fragments = this.get('fragments') || defaultFragments; this.set('fragments', fragments); }, show() { return this.get('fragments').map(fragmentToString).join(''); }, addSerialized(serialized) { serialized['fragments'] = this.get('fragments'); return serialized; }, generateList() { // This algorithm is very inefficient due to concatenation and flattening. const fragments = Ember.copy(this.get('fragments')); let firstFragment = fragments.shiftObject(); let urlList = [[firstFragment.value]]; fragments.forEach((fragment) => { let augmentedList = urlList.map((fragmentList) => { return augmentFragmentList(fragmentList, fragment); }); urlList = flatten(augmentedList); }); return urlList; } }); const FeedUrl = StartUrl.extend({ type: 'feed', optionsTitle: 'Feed', componentName: 'project-structure-spider-feed-url', optionsComponentName: 'feed-url-options', show() { return this._raw_url(); }, _raw_url() { const url = this.get('url'); const notRaw = !url.includes('raw'); if (url.includes('gist.github') && notRaw) { const trailingSlash = (url.slice(-1) === '/') ? '' : '/'; return url + trailingSlash + 'raw'; } if (url.includes('dropbox.com') && notRaw) { return url + '&raw=1'; } if (url.includes('docs.google.com') && !url.includes('export')) { return url.split('/') .slice(0, -1) .concat('export?format=txt') .join('/'); } return url; } }); export default function buildStartUrl(startUrl) { const urls = { 'url': StartUrl, 'feed': FeedUrl, 'generated': GeneratedUrl }; const urlType = startUrl.type || 'url'; return urls[urlType].create(startUrl); } ================================================ FILE: portiaui/app/resolver.js ================================================ import Resolver from 'ember-resolver'; export default Resolver; ================================================ FILE: portiaui/app/router.js ================================================ import Ember from 'ember'; import config from './config/environment'; const Router = Ember.Router.extend({ location: config.locationType }); Router.map(function() { this.route('projects', function() { this.route('project', {path: ":project_id"}, function() { this.route('spider', {path: "spiders/:spider_id"}, function() { this.route('sample', {path: "samples/:sample_id"}, function() { this.route('data', function() { this.route('annotation', {path: "annotations/:annotation_id"}, function() { this.route('options'); }); this.route('item', {path: "items/:item_id"}); }); }); this.route('options'); this.route('link-options'); this.route('start-url', {path: "start-urls/:start_url_id"}, function() { this.route('options'); }); }); this.route('schema', {path: "schemas/:schema_id"}, function() { this.route('field', {path: "fields/:field_id"}, function() { this.route('options'); }); this.route('options'); }); this.route("conflicts", function(){ this.route("conflict", {path: ':file_path'}); }); this.route('compatibility', {path: "*path"}); }); }); this.route('browsers'); }); export default Router; ================================================ FILE: portiaui/app/routes/.gitkeep ================================================ ================================================ FILE: portiaui/app/routes/application.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ }); ================================================ FILE: portiaui/app/routes/browsers.js ================================================ import Ember from 'ember'; let browsers = [ { name: 'Chrome', alt: 'Chrome logo', src: '/assets/images/chrome-logo.jpg', href: 'https://www.google.com/chrome/browser/desktop/' }, { name: 'Firefox', alt: 'Firefox logo', src: '/assets/images/firefox-logo.png', href: 'https://www.mozilla.org/en-US/firefox/new/' } ]; export default Ember.Route.extend({ model() { return browsers; } }); ================================================ FILE: portiaui/app/routes/index.js ================================================ import Ember from 'ember'; import hasBrowserFeatures from '../utils/browser-features'; function identity(x) { return x; } export default Ember.Route.extend({ model() { return hasBrowserFeatures(); }, redirect(model) { let hasFeatures = model.every(identity); let nextRoute = hasFeatures ? 'projects' : 'browsers'; this.replaceWith(nextRoute); } }); ================================================ FILE: portiaui/app/routes/projects/project/compatibility.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { return params; }, redirect({path}, {queryParams}) { // conflicts route has the same path if (path === 'items') { this.transitionTo('projects.project', { queryParams: queryParams }); return; } const fragments = path.split('/'); if (fragments.length === 1) { this.transitionTo('projects.project.spider', fragments[0], { queryParams: queryParams }); } else { this.transitionTo('projects.project.spider.sample', fragments[0], fragments[1], { queryParams: queryParams }); } } }); ================================================ FILE: portiaui/app/routes/projects/project/conflicts/conflict.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { var allConflicts = this.modelFor("projects.project.conflicts"); var file = atob(params.file_path); return { file: file, contents: allConflicts[file], }; }, renderTemplate() { this.render('projects/project/conflicts/topbar', { into: 'application', outlet: 'top-bar', }); this.render('projects/project/conflicts/resolver', { into: 'application', outlet: 'main', }); }, }); ================================================ FILE: portiaui/app/routes/projects/project/conflicts.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ model() { return $.post('/projects', JSON.stringify({ cmd: 'conflicts', args: [this.modelFor("projects.project").id] })); }, renderTemplate() { this.render('projects/project/conflicts/file-selector', { into: 'application', outlet: 'side-bar', }); this.render('projects/project/conflicts/help', { into: 'application', outlet: 'main', }); }, }); ================================================ FILE: portiaui/app/routes/projects/project/schema/field/options.js ================================================ import Ember from 'ember'; import OptionsRoute from '../../../../../mixins/options-route'; export default Ember.Route.extend(OptionsRoute, { model() { return this.modelFor('projects.project.schema.field'); }, renderTemplate() { this.render('projects/project/schema/field/options', { into: 'options-panels', outlet: 'options-panels' }); }, actions: { close() { this.transitionTo('projects.project.schema.field'); } } }); ================================================ FILE: portiaui/app/routes/projects/project/schema/field.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { return this.store.peekRecord('field', params.field_id); } }); ================================================ FILE: portiaui/app/routes/projects/project/schema.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { return this.store.peekRecord('schema', params.schema_id); }, afterModel(model) { return model.reload(); }, renderTemplate() { this.render('projects/project/schema/structure', { into: 'projects/project/structure', outlet: 'project-structure' }); }, actions: { error: function() { this.transitionTo('projects.project', this.modelFor('projects.project')); } } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/link-options.js ================================================ import Ember from 'ember'; import OptionsRoute from '../../../../mixins/options-route'; export default Ember.Route.extend(OptionsRoute, { model() { return this.modelFor('projects.project.spider'); }, renderTemplate() { this.render('projects/project/spider/link-options', { into: 'options-panels', outlet: 'options-panels' }); }, actions: { close() { this.transitionTo('projects.project.spider'); } } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/options.js ================================================ import Ember from 'ember'; import OptionsRoute from '../../../../mixins/options-route'; export default Ember.Route.extend(OptionsRoute, { model() { return this.modelFor('projects.project.spider'); }, renderTemplate() { this.render('projects/project/spider/options', { into: 'options-panels', outlet: 'options-panels' }); }, actions: { close() { this.transitionTo('projects.project.spider'); } } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/sample/data/annotation/options.js ================================================ import Ember from 'ember'; import OptionsRoute from '../../../../../../../mixins/options-route'; export default Ember.Route.extend(OptionsRoute, { model() { return this.modelFor('projects.project.spider.sample.data.annotation'); }, afterModel() { let extractorsPromise = this.modelFor('projects.project').get('extractors'); if (!extractorsPromise.get('isPending')) { extractorsPromise = extractorsPromise.reload(); } return extractorsPromise; }, renderTemplate() { this.render('projects/project/spider/sample/data/annotation/options', { into: 'options-panels', outlet: 'options-panels' }); }, actions: { close() { this.transitionTo('projects.project.spider.sample.data.annotation'); } } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/sample/data/annotation.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ uiState: Ember.inject.service(), selectedElement: Ember.computed.alias('uiState.viewPort.selectedElement'), selectedModel: Ember.computed.alias('uiState.viewPort.selectedModel'), model(params) { return this.store.peekRecord('annotation', params.annotation_id); }, afterModel(model) { if (this.get('selectedModel') !== model) { this.setProperties({ selectedElement: null, selectedModel: model }); } }, deactivate() { this.setProperties({ selectedElement: null, selectedModel: null }); }, actions: { error() { this.transitionTo('projects.project.spider.sample.data'); } } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/sample/data/item.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { return this.store.peekRecord('item', params.item_id); }, actions: { error() { this.transitionTo('projects.project.spider.sample.data'); } } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/sample/data.js ================================================ import Ember from 'ember'; const { inject: { service }, run } = Ember; export default Ember.Route.extend({ annotationStructure: service(), extractedItems: service(), browser: service(), init() { this._super(...arguments); this.scheduledRenderOverlays = null; }, model() { return this.modelFor('projects.project.spider.sample'); }, afterModel(model) { this.updateDataStructure(model); this.get('extractedItems').update(); }, activate() { this.get('browser').setAnnotationMode(); this.controllerFor('projects.project').setClickHandler(this.viewPortClick.bind(this)); }, deactivate() { this.updateDataStructure(null); if (this.scheduledRenderOverlays) { run.cancel(this.scheduledRenderOverlays); } this.get('browser').clearAnnotationMode(); this.controllerFor('projects.project').clearClickHandler(); }, renderTemplate() { this.render('projects/project/spider/sample/data/structure', { into: 'projects/project/spider/sample/structure', outlet: 'sample-structure' }); this.render('projects/project/spider/sample/data/tools', { into: 'tool-panels', outlet: 'tool-panels' }); this.render('projects/project/spider/sample/data/toolbar', { into: 'projects/project/spider/sample/toolbar', outlet: 'browser-toolbar' }); this.scheduledRenderOverlays = run.next(this, this.renderOverlayTemplate); }, renderOverlayTemplate() { this.scheduledRenderOverlays = null; this.render('projects/project/spider/sample/data/overlays', { into: 'projects/project', outlet: 'browser-overlays' }); }, updateDataStructure(model) { const annotationStructure = this.get('annotationStructure'); const currentModel = this._dataStructureModel; if (currentModel !== model) { annotationStructure.removeDataStructure(currentModel); annotationStructure.addDataStructure(model); this._dataStructureModel = model; } }, viewPortClick() { this.get('controller').send('selectElement', ...arguments); } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/sample/index.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ redirect(model, {queryParams}) { this.transitionTo('projects.project.spider.sample.data', { /* The queryParams in the transition object have been processed and keys with empty values have been removed. If we use the same object for the new transition the unspecified values will keep their current values. This means we can't automatically pass through query parameters that have intentionally been emptied. */ queryParams: Ember.assign({ url: null, baseurl: null }, queryParams) }); } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/sample.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ browser: Ember.inject.service(), model(params) { return this.store.peekRecord('sample', params.sample_id); }, afterModel(model) { return model.reload().then(model => { return model; }); }, renderTemplate() { this.render('projects/project/spider/sample/structure', { into: 'projects/project/spider/structure', outlet: 'spider-structure' }); this.render('projects/project/spider/sample/toolbar', { into: 'projects/project', outlet: 'browser-toolbar' }); }, actions: { error() { this.transitionTo('projects.project.spider', this.modelFor('projects.project.spider')); } } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/start-url/options.js ================================================ import Ember from 'ember'; import OptionsRoute from '../../../../../mixins/options-route'; export default Ember.Route.extend(OptionsRoute, { model() { const startUrl = this.modelFor('projects.project.spider.start-url'); return { spider: this.getSpider(), startUrlId: this.getSpider().get('startUrls').indexOf(startUrl) }; }, afterModel(model) { if (!model) { this.transitionToSpider(); } }, renderTemplate() { this.render('projects/project/spider/start-url/options', { into: 'options-panels', outlet: 'options-panels' }); }, getSpider() { return this.modelFor('projects.project.spider'); }, transitionToSpider() { this.transitionTo('projects.project.spider', this.getSpider()); }, actions: { closeOptions() { this.transitionToSpider(); } } }); ================================================ FILE: portiaui/app/routes/projects/project/spider/start-url.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { const spider = this.modelFor('projects.project.spider'); return spider.get('startUrls').objectAt(params.start_url_id); } }); ================================================ FILE: portiaui/app/routes/projects/project/spider.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ browser: Ember.inject.service(), model(params) { return this.store.peekRecord('spider', params.spider_id); }, afterModel(model) { return model.reload().then(() => model.get('samples')); }, redirect(model, {queryParams}) { /* The route may be loaded from a partial model without all data from the backed, and an undefined firstUrl. This is fired after afterModel so the model will have been reloaded from the backend. */ if (queryParams.url === undefined && queryParams.baseurl === undefined) { const url = model.get('firstUrl'); if (url === undefined) { return; } /* Transition in the next frame to prevent an issue where sometimes the route fails to render. */ Ember.run.next(() => { this.transitionTo('projects.project.spider', { queryParams: { url, baseurl: null } }); }); } }, setupController(controller) { this._super(...arguments); Ember.run.next(function () { controller.activate(); }); }, resetController(controller, isExiting) { Ember.run.next(function () { controller.deactivate(); if (!isExiting) { controller.activate(); } }); }, renderTemplate() { this.render('projects/project/spider/structure', { into: 'projects/project/structure', outlet: 'project-structure' }); this.render('projects/project/spider/overlays', { into: 'projects/project', outlet: 'browser-overlays' }); this.render('projects/project/spider/tools', { into: 'tool-panels', outlet: 'tool-panels' }); this.render('projects/project/spider/toolbar', { into: 'projects/project', outlet: 'browser-toolbar' }); }, actions: { error() { this.transitionTo('projects.project', this.modelFor('projects.project')); }, transitionToFragments(start_url_id) { this.transitionTo('projects.project.spider.start-url.options', start_url_id); }, closeOptions() { let spider = this.modelFor('projects.project.spider'); this.transitionTo('projects.project.spider', spider); } } }); ================================================ FILE: portiaui/app/routes/projects/project.js ================================================ import Ember from 'ember'; const { inject: { service } } = Ember; export default Ember.Route.extend({ browser: service(), changes: service(), notificationManager: service(), uiState: service(), beforeModel() { this.store.unloadAll('spider'); this.store.unloadAll('schema'); this.set('uiState.currentSpider', null); }, model(params) { this.set('projectId', params.project_id); return this.store.findRecord('project', params.project_id); }, setupController(controller, model) { this._super(controller, model); controller.set('projects', this.controllerFor('projects')); }, deactivate() { this.set('browser.url', null); }, renderTemplate() { this.render({ into: 'application', outlet: 'main' }); this.render('projects/project/structure', { into: 'application', outlet: 'side-bar' }); this.render('options-panels', { into: 'application', outlet: 'options-panels' }); this.render('tool-panels', { into: 'application', outlet: 'tool-panels' }); this.render('projects/project/toolbar', { into: 'projects/project', outlet: 'browser-toolbar' }); }, projectNotFound() { const id = this.get('projectId'); const errorMsg = `Project with id '${id}' not found.`; this.get('notificationManager').showErrorNotification(errorMsg); }, actions: { error: function() { this.projectNotFound(); this.transitionTo('projects'); }, conflict() { this.transitionTo('projects.project.conflicts'); }, reload() { this.transitionTo('projects.project'); this.store.unloadAll('spider'); this.store.unloadAll('schema'); this.refresh(); } } }); ================================================ FILE: portiaui/app/routes/projects.js ================================================ import Ember from 'ember'; export default Ember.Route.extend({ model() { return this.store.findAll('project'); } }); ================================================ FILE: portiaui/app/serializers/application.js ================================================ import DS from "ember-data"; export default DS.JSONAPISerializer.extend({ normalize(modelClass, resourceHash) { const resource = this._super(...arguments); // add resource instance link to data, we use this to resolve the url // for subsequent requests if (resourceHash.links) { resource.data.links = resourceHash.links; } return resource; }, serialize(snapshot, options) { const json = this._super(...arguments); // partial serialization based on the partial option if (options && options.partial) { const data = json.data; let keys = new Set(); for (let key of options.partial) { let payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key) { payloadKey = this.keyForAttribute(key, 'serialize'); } keys.add(payloadKey); } for (let field of Object.keys(data.attributes)) { if (!keys.has(field)) { delete data.attributes[field]; } } if (!Object.keys(data.attributes).length) { delete data.attributes; } for (let field of Object.keys(data.relationships)) { if (!keys.has(field)) { delete data.relationships[field]; } } if (!Object.keys(data.relationships).length) { delete data.relationships; } } return json; } }); ================================================ FILE: portiaui/app/services/annotation-structure.js ================================================ import Ember from 'ember'; import { AnnotationSelectorGenerator, ContainerSelectorGenerator, createSelectorGenerators } from '../utils/selectors'; const ElementStructure = Ember.Object.extend({ definition: null, selectorMatcher: null, init() { this._super(...arguments); this.addObservers(); }, destroy() { this.removeObservers(); this._super(...arguments); }, updateDefinition: Ember.observer('definition', function() { this.removeObservers(); this.addObservers(); }), addObservers() { const allElements = []; this.set('annotations', Ember.Object.create()); this.set('elements', Ember.Object.create({ all: allElements })); const bindings = this.bindings = []; const definition = this.get('definition'); const selectorMatcher = this.get('selectorMatcher'); const setup = element => { const annotation = element.annotation; const children = element.children; const guid = Ember.guidFor(annotation); const setElements = elements => { (annotation.get('elements') || []).forEach(element => { allElements.removeObject(element); const guid = Ember.guidFor(element); const annotations = this.get(`annotations.${guid}`); if (annotations) { annotations.removeObject(annotation); if (!annotations.length) { this.set(`annotations.${guid}`, undefined); } } }); elements.forEach(element => { allElements.addObject(element); const guid = Ember.guidFor(element); let annotations = this.get(`annotations.${guid}`); if (!annotations) { annotations = []; this.set(`annotations.${guid}`, annotations); this.notifyPropertyChange('annotations'); } annotations.addObject(annotation); }); if (!annotation.get('isDeleted')) { annotation.set('elements', elements); } this.set(`elements.${guid}`, elements); this.notifyPropertyChange('elements'); }; if (children) { children.forEach(setup); let selector = null; const observer = () => { if (selector) { selectorMatcher.unRegister(selector, setElements); } selector = annotation.get('repeatedSelector') || annotation.get('selector'); if (selector) { selectorMatcher.register(selector, setElements); setElements(selectorMatcher.query(selector)); } }; let scheduledObserver = null; bindings.push({ annotation, setup() {}, teardown() { Ember.run.cancel(scheduledObserver); if (selector) { selectorMatcher.unRegister(selector, setElements); } annotation.setProperties({ elements: undefined }); }, observer() { // allow the bindings to sync first scheduledObserver = Ember.run.scheduleOnce('sync', observer); }, observerPaths: ['selector', 'repeatedSelector'] }); } else { let selector = null; const observer = () => { if (selector) { selectorMatcher.unRegister(selector, setElements); } selector = annotation.get('selector'); if (selector) { selectorMatcher.register(selector, setElements); setElements(selectorMatcher.query(selector)); } }; let scheduledObserver = null; bindings.push({ annotation, setup() {}, teardown() { Ember.run.cancel(scheduledObserver); if (selector) { selectorMatcher.unRegister(selector, setElements); } annotation.setProperties({ elements: undefined }); }, observer() { // allow the bindings to sync first scheduledObserver = Ember.run.scheduleOnce('sync', observer); }, observerPaths: ['selector'] }); } }; definition.forEach(setup); for (let {setup} of bindings) { if (setup) { setup(); } } for (let {annotation, observer, observerPaths} of bindings) { if (observer) { for (let path of observerPaths) { Ember.addObserver(annotation, path, observer); } observer(); } } }, removeObservers() { for (let {annotation, observer, observerPaths, teardown} of this.bindings) { if (observer) { for (let path of observerPaths) { Ember.removeObserver(annotation, path, observer); } } if (teardown) { teardown(); } } this.bindings = []; for (let property of ['annotations', 'elements']) { const object = this.get(property); if (object) { object.destroy(); } this.set(property, null); } } }); const DataElementStructure = ElementStructure.extend({ model: null, // a sample definition: [], setDefinition: Ember.on('init', Ember.observer('model.orderedAnnotations.[]', function() { const sample = this.get('model'); if (!sample) { this.set('definition', []); } const structurePromise = createStructure(sample); this.currentPromise = structurePromise; structurePromise.then(structure => { if (structurePromise === this.currentPromise) { delete this.currentPromise; this.set('definition', structure); } }); })) }); export function createStructure(sample) { return sample.get('items').then(items => Ember.RSVP.filter(items.toArray(), item => item && !item.get('isDeleted') ).then(filteredItems => Ember.RSVP.map(filteredItems, item => Ember.RSVP.hash({ annotation: item, children: item.get('annotations').then(function mapper(annotations) { if (!annotations) { return []; } return Ember.RSVP.filter(annotations.toArray(), annotation => !annotation.get('isDeleted') ).then(filteredAnnotations => Ember.RSVP.map(filteredAnnotations, annotation => { if (annotation.constructor.modelName === 'annotation') { return { annotation }; } else if (annotation.constructor.modelName === 'item') { return Ember.RSVP.hash({ annotation, children: annotation.get('annotations').then(mapper) }); } }) ); }) }) ) ) ); } export function updateStructureSelectors(structure, selectorMatcher) { const selectorGenerators = createSelectorGenerators(structure, selectorMatcher); for (let [annotation, selectorGenerator] of selectorGenerators) { const selector = selectorGenerator.get('selector'); if (selectorGenerator instanceof AnnotationSelectorGenerator) { annotation.setProperties({ selector, xpath: selectorGenerator.get('xpath'), repeated: selectorGenerator.get('repeatedAnnotation') }); if (annotation.get('selectionMode') === 'css') { annotation.setSelector(selector); } } else if (selectorGenerator instanceof ContainerSelectorGenerator) { const containerSelector = selectorGenerator.get('containerSelector'); const siblings = selectorGenerator.get('siblings'); const element = selector ? selectorMatcher.query(selector) : []; if (!element.length) { annotation.setProperties({ selector: null, repeatedSelector: null, siblings: 0 }); } else if (element.length > 1) { annotation.setProperties({ selector: containerSelector, repeatedSelector: selector, siblings }); } else { annotation.setProperties({ selector, repeatedSelector: null, siblings }); } } selectorGenerator.destroy(); } } export default Ember.Service.extend({ selectorMatcher: Ember.inject.service(), addStructure(model, attribute, Class) { if (!model) { return; } const selectorMatcher = this.get('selectorMatcher'); model.set(attribute, Class.create({ selectorMatcher, model })); }, removeStructure(model, attribute) { if (!model) { return; } const structure = model.get(attribute); if (structure) { structure.destroy(); model.set(attribute, null); } }, addDataStructure(sample) { this.addStructure(sample, 'dataStructure', DataElementStructure); }, removeDataStructure(sample) { this.removeStructure(sample, 'dataStructure'); } }); ================================================ FILE: portiaui/app/services/browser.js ================================================ import Ember from 'ember'; const { computed } = Ember; import { cleanUrl, renameAttr } from '../utils/utils'; export const NAVIGATION_MODE = 'navigation'; export const ANNOTATION_MODE = 'data-annotation'; export const INTERACTION_MODES = new Set([ANNOTATION_MODE]); export const DEFAULT_MODE = NAVIGATION_MODE; /* jshint ignore:start */ const META_STYLE = ``; /* jshint ignore:end */ export default Ember.Service.extend(Ember.Evented, { extractedItems: Ember.inject.service(), webSocket: Ember.inject.service(), backBuffer: [], cssEnabled: true, document: null, forwardBuffer: [], loading: false, mode: DEFAULT_MODE, _disabled: true, _url: null, baseurl: null, validUrl: true, invalidUrl: computed.not('validUrl'), disabled: Ember.computed('_disabled', 'webSocket.closed', 'mode', { get() { return this.get('_disabled') || this.get('webSocket.closed') || this.get('mode') !== NAVIGATION_MODE; }, set(key, value) { this.set('_disabled', value); return value || this.get('webSocket.closed') || this.get('mode') !== NAVIGATION_MODE; } }), isInteractionMode: Ember.computed('mode', function() { return INTERACTION_MODES.has(this.get('mode')); }), url: Ember.computed('_url', { get() { return this.get('_url'); }, set(key, value) { return this.go(value); } }), $document: Ember.computed('document', function() { const document = this.get('document'); return document ? Ember.$(document) : null; }), init() { this._super(...arguments); this.on('contentChanged', () => { Ember.run.next(() => { Ember.run.scheduleOnce('sync', this, 'checkCSS'); }); }); }, resetUrl: Ember.observer('document', function() { if (!this.get('document')) { this.setProperties({ '_url': null, 'baseurl': null }); } }), invalidateUrl() { this.set('validUrl', false); }, go(url) { this.set('validUrl', true); const currentUrl = this.get('_url'); url = cleanUrl(url); if (url && url !== currentUrl) { this._extract(); this.beginPropertyChanges(); if (currentUrl) { this.get('backBuffer').pushObject(currentUrl); } this.set('_url', url); this.set('forwardBuffer', []); this.endPropertyChanges(); } return url; }, back() { this._updateBuffers(this.get('backBuffer'), this.get('forwardBuffer')); }, forward() { this._updateBuffers(this.get('forwardBuffer'), this.get('backBuffer')); }, reload() { this.notifyPropertyChange('_url'); }, checkCSS() { const $iframe = this.get('$document'); const $showMetaStyleElement = $iframe.find('style[title="portia-show-meta"]'); const cssEnabled = !$showMetaStyleElement.length; this.set('cssEnabled', cssEnabled); }, disableCSS() { if (![ANNOTATION_MODE].includes(this.get('mode'))) { return; } const iframe = this.get('document'); if (this.get('cssEnabled') && iframe) { const $iframe = this.get('$document'); const $styles = $iframe.find( 'style:not([title="portia-show-meta"]), link[rel="stylesheet"]'); renameAttr($styles, 'media', 'data-portia-hidden-media'); // disable stylesheets using an impossible media query $styles.attr('media', '(width: -1px)'); renameAttr($iframe.find('[style]'), 'style', 'data-portia-hidden-style'); $iframe.find('body').append(META_STYLE); // jshint ignore:line this.set('cssEnabled', false); } }, enableCSS() { if (![ANNOTATION_MODE].includes(this.get('mode'))) { return; } const iframe = this.get('document'); if (!this.get('cssEnabled') && iframe) { const $iframe = this.get('$document'); $iframe.find('style[title="portia-show-meta"]').remove(); const $styles = $iframe.find( 'style:not([title="portia-show-meta"]), link[rel="stylesheet"]'); $styles.attr('media', null); renameAttr($styles, 'data-portia-hidden-media', 'media'); renameAttr($iframe.find('[data-portia-hidden-style]'), 'data-portia-hidden-style', 'style'); this.set('cssEnabled', true); } }, setAnnotationMode() { this.set('mode', ANNOTATION_MODE); }, clearAnnotationMode() { if (this.get('mode') === ANNOTATION_MODE) { this.set('mode', DEFAULT_MODE); this.enableCSS(); } }, _updateBuffers(currentBuffer, otherBuffer) { if (currentBuffer.length) { this.beginPropertyChanges(); otherBuffer.pushObject(this.get('_url')); const url = currentBuffer.popObject(); this._extract(); this.setProperties({ '_url': url, 'baseurl': null }); this.endPropertyChanges(); } }, _extract() { this.get('extractedItems').activateExtraction(); } }); ================================================ FILE: portiaui/app/services/capabilities.js ================================================ import Ember from 'ember'; export default Ember.Service.extend({ ajax: Ember.inject.service(), fetchCapabilities: Ember.on('init', function() { this.get('ajax').request('/server_capabilities').then(capabilities => { this.setProperties(capabilities); }, () => { Ember.run.later(this, this.fetchCapabilities, 5000); }); }) }); ================================================ FILE: portiaui/app/services/changes.js ================================================ import Ember from 'ember'; const { observer, computed, inject: { service }, run: { next } } = Ember; export default Ember.Service.extend({ uiState: service(), capabilities: service(), project: computed.readOnly('uiState.models.project'), versionControlled: computed.readOnly('capabilities.capabilities.version_control'), changes: null, hasChanges: computed('changes', 'versionControlled', 'hasChanges', { get() { const changes = this.get('changes'); const project = this.get('project'); if (changes === null || (project && this.get('_project_id') !== project.get('id'))) { this._checkProjectChanges(); } else { return changes; } }, set(_, value) { if (this.get('versionControlled') && value) { this.set('changes', true); return true; } else { this.set('changes', false); return false; } } }), _project_id: null, init() { this._checkProjectChanges(); }, projectChanged: observer('project.id', function() { if (this.get('project.id') !== this.get('_project_id')) { this._checkProjectChanges(); } }), _checkProjectChanges() { let project = this.get('project'); if (!(project && this.get('versionControlled'))) { return false; } next(this, () => { project.status().then(status => { const hasChanges = !!(status && status.meta && status.meta.changes && status.meta.changes.length); this.set('_project_id', this.get('project.id')); this.set('changes', hasChanges); }); }); } }); ================================================ FILE: portiaui/app/services/clock.js ================================================ import Ember from 'ember'; // based on an idea from https://www.rvdh.de/2014/11/14/time-based-triggers-in-ember-js/ export default Ember.Service.extend({ time: new Date(), metronome: Ember.on('init', function() { const now = new Date(); const interval = 1000 - (+now % 1000); this.set('time', now); Ember.run.later(this, this.metronome, interval); }) }); ================================================ FILE: portiaui/app/services/dispatcher.js ================================================ import Ember from 'ember'; import Sample from '../models/sample'; import { includesUrl } from '../utils/start-urls'; import buildStartUrl from '../models/start-url'; import {createStructure} from './annotation-structure'; import {getDefaultAttribute, hasContentAttribute} from '../components/inspector-panel'; import {updateStructureSelectors} from '../services/annotation-structure'; import { task } from 'ember-concurrency'; export function computedCanAddSpider() { return Ember.computed('browser.url', function() { return this.get('browser.url'); }); } export function computedCanAddSample(spiderPropertyName) { return Ember.computed('browser.url', 'browser.document', 'browser.loading', `${spiderPropertyName}.samples.@each.url`, 'browser.loading', function() { const url = this.get('browser.url'); const document = this.get('browser.document'); const loading = this.get('browser.loading'); return (url && document && !loading && !this.get(`${spiderPropertyName}.samples`).isAny('url', url)); }); } export function computedEditableSample(spiderPropertyName) { return Ember.computed('browser.url', `${spiderPropertyName}.samples.@each.url`, function() { const url = this.get('browser.url'); if (!url) { return; } return this.get(`${spiderPropertyName}.samples`).findBy('url', url); }); } export default Ember.Service.extend({ api: Ember.inject.service(), browser: Ember.inject.service(), routing: Ember.inject.service('-routing'), selectorMatcher: Ember.inject.service(), store: Ember.inject.service(), uiState: Ember.inject.service(), webSocket: Ember.inject.service(), addProject(name, redirect = false) { const store = this.get('store'); const project = store.createRecord('project', { name, }); return project.save().then(() => { if (redirect) { const routing = this.get('routing'); routing.transitionTo('projects.project', [project], {}, true); } return project; }); }, addSchema(project, redirect = false) { const name = `schema${project.get('schemas.length') + 1}`; return this.addNamedSchema(project, name, redirect); }, addNamedSchema(project, name, redirect = false) { const store = this.get('store'); const schema = store.createRecord('schema', { name, project }); return schema.save().then(() => { if (redirect) { schema.set('new', true); const routing = this.get('routing'); routing.transitionTo('projects.project.schema', [schema], {}, true); } return schema; }); }, addField(schema, type, redirect = false) { const name = `field${schema.get('fields.length') + 1}`; return this.addNamedField(schema, name, type, redirect); }, addNamedField(schema, name, type, redirect = false) { const store = this.get('store'); const field = store.createRecord('field', { name, type: type || 'text', schema }); return field.save().then((field) => { if (redirect) { field.set('new', true); const routing = this.get('routing'); routing.transitionTo('projects.project.schema.field', [field], {}, true); } return field; }); }, addSpider(project, redirect = false) { const url = this.get('browser.url'); if (!url) { return; } let name = url; const matches = url.match('//([a-zA-Z0-9\._-]*)'); const store = this.get('store'); if (matches && matches.length) { name = matches.slice(-1)[0]; } else { name = url.replace(/[^a-zA-Z0-9_\.-]/g, ''); } let baseName = name; let counter = 1; while (store.peekRecord('spider', name)) { name = `${baseName}_${counter}`; counter += 1; } const spider = store.createRecord('spider', { id: name, startUrls: [buildStartUrl({ url: url })], project }); spider.set('project', project); spider.save().then(() => { if (redirect) { spider.set('new', true); const routing = this.get('routing'); routing.transitionTo('projects.project.spider', [spider], {}, true); } }); return spider; }, addStartUrl(spider, url) { if (url && !includesUrl(spider, url)) { return buildStartUrl({ url: url }).save(spider); } }, addGeneratedUrl(spider, url) { let spec = { type: 'generated' }; if (!url || includesUrl(spider, url)) { spec.url = 'http://'; return buildStartUrl(spec).save(spider); } if (!includesUrl(spider, url)) { spec.url = url; return buildStartUrl(spec).save(spider); } }, addFeedUrl(spider, url) { return buildStartUrl({ url: url, type: 'feed' }).save(spider); }, addSample(spider, redirect = false) { const url = this.get('browser.url'); const document = this.get('browser.document'); const loading = this.get('browser.loading'); if (!url || !document || loading) { return; } const store = this.get('store'); const name = Sample.normalizeTitle(this.get('browser.document').title); const sample = store.createRecord('sample', { name, body: 'original_body', url, spider }); sample.save().then(() => { this.get('webSocket')._sendPromise({ _command: 'save_html', project: spider.get('project.id'), spider: spider.get('id'), sample: sample.get('id') }).then(() => { if (redirect) { sample.set('new', true); const routing = this.get('routing'); routing.transitionTo('projects.project.spider.sample', [sample], {}, true); } }); }); return sample; }, addItem(sample, redirect = false) { return this._addItem({ sample }, redirect); }, addNestedItem(parentItem, redirect = false) { return this._addItem({ parent: parentItem }, redirect); }, _addItem(attributes, redirect = false) { const store = this.get('store'); const item = store.createRecord('item', attributes); this.saveAnnotationAndRelatedSelectors(item).then(() => { if (redirect) { item.set('new', true); const routing = this.get('routing'); routing.transitionTo('projects.project.spider.sample.data.item', [item], {}, true); } }); return item; }, addAnnotation(item, element, attribute, redirect = false) { if (!item) { let activeItem; let activeAnnotation; if (activeItem = this.get('uiState.models.item')) { item = activeItem; } else if (activeAnnotation = this.get('uiState.models.annotation')) { item = activeAnnotation.get('parent'); } else { item = this.get('uiState.models.sample.items.lastObject'); } } const store = this.get('store'); const annotation = store.createRecord('annotation', { parent: item }); if (element) { annotation.addElement(element); attribute = attribute || getDefaultAttribute(element); if (hasContentAttribute(element)) { annotation.set('text_content', 'text-content'); } } if (attribute !== undefined) { annotation.set('attribute', attribute); } this.saveAnnotationAndRelatedSelectors(annotation).then(() => { if (redirect) { annotation.set('new', true); } if (element) { this.selectAnnotationElement(annotation, element, redirect); } else if (redirect) { this.selectAnnotation(annotation); } }); return annotation; }, saveAnnotationAndRelatedSelectors(annotation) { if (!annotation.get('ownerSample')) { return new Ember.RSVP.Promise.resolve(); } return annotation.get('ownerSample').then(sample => this.updateSampleSelectors(sample).then(() => { const coalesce = []; for (let child of sample.get('orderedChildren')) { if (child === annotation) { continue; } if (child.constructor.modelName === 'item') { coalesce.push({ model: child, options: { partial: ['selector', 'repeatedSelector', 'siblings'] } }); } else if (child.constructor.modelName === 'annotation') { coalesce.push({ model: child, options: { partial: ['selectionMode', 'selector', 'xpath'] } }); } } return annotation.save(coalesce.length ? { coalesce } : undefined); })); }, addAnnotationTypeExtractor(annotation, type) { const store = this.get('store'); const project = annotation.get('ownerSample.spider.project'); return project.get('extractors').then(extractors => { const existing = extractors.find(extractor => { return extractor.get('type') === 'type' && extractor.get('value') === type; }); let extractorPromise; if (existing) { extractorPromise = Ember.RSVP.resolve(existing); } else { const extractor = store.createRecord('extractor', { project, type: 'type', value: type }); extractorPromise = extractor.save(); } return extractorPromise.then(extractor => { annotation.get('extractors').pushObject(extractor); return annotation.save().then(() => extractor); }); }); }, addAnnotationRegexExtractor(annotation, extractor) { annotation.get('extractors').pushObject(extractor); return annotation.save().then(() => extractor); }, addNewAnnotationRegexExtractor(annotation) { const store = this.get('store'); const project = annotation.get('ownerSample.spider.project'); const extractor = store.createRecord('extractor', { project, type: 'regex', value: '(.*)' }); return extractor.save().then(extractor => { extractor.set('new', true); annotation.get('extractors').pushObject(extractor); return annotation.save().then(() => extractor); }); }, addFragment(startUrl) { let emptyFragment = { type: 'fixed', value: '' }; startUrl.fragments.addObject(emptyFragment); }, changeId(model, json) { // HACK: Ember data does not support changing a record's id // This mechanism bypasses this contraint. const store = this.get('store'); let internalModel = model._internalModel; const newId = json.data.id; // Update internal store with internal model const recordMap = store.typeMapFor(internalModel.type).idToRecord; delete recordMap[internalModel.id]; recordMap[newId] = internalModel; // Allows changing ED model id internalModel.id = newId; // Allows adapters to infer the correct url internalModel._links.self = json.data.links.self; model.set('id', newId); }, changeSpiderName(spider) { if (!spider.get('name') || spider.get('name') === spider.get('id')) { return new Ember.RSVP.Promise(resolve => resolve({ data: { links: {self: spider._internalModel._links.self}, id: spider.get('id') }})); } const data = { name: spider.get('name') }; return this.get('api').post('rename', { model: spider, jsonData: data }); }, changeAnnotationSource(annotation, attribute) { if (annotation) { annotation.set('attribute', attribute); annotation.save(); } }, removeSchema(schema) { const currentSchema = this.get('uiState.models.schema'); if (schema === currentSchema) { const routing = this.get('routing'); routing.transitionTo('projects.project', [], {}, true); } schema.get('fields').then(fields => { for (let field of (fields.currentState || [])) { field.unloadRecord(); } schema.destroyRecord(); }); }, removeField(field) { const currentField = this.get('uiState.models.field'); if (field === currentField) { const routing = this.get('routing'); routing.transitionTo('projects.project.schema', [], {}, true); } field.destroyRecord(); }, removeSpider(spider) { const currentSpider = this.get('uiState.models.spider'); if (spider === currentSpider) { const routing = this.get('routing'); routing.transitionTo('projects.project', [], {}, true); } spider.destroyRecord(); }, removeStartUrl(spider, url) { spider.get('startUrls').removeObject(url); spider.save(); }, replaceStartUrl(spider, oldUrl, newUrl) { const urls = spider.get('startUrls'); let oldStartUrl = urls.filterBy('url', oldUrl)[0]; urls.removeObject(oldStartUrl); if (!includesUrl(spider, newUrl)) { urls.addObject(buildStartUrl({url: newUrl, type: 'url'})); } spider.save(); }, removeSample(sample) { const currentSample = this.get('uiState.models.sample'); if (sample === currentSample) { const routing = this.get('routing'); routing.transitionTo('projects.project.spider', [], {}, true); } sample.destroyRecord(); }, removeItem(item) { const currentItem = this.get('uiState.models.item'); const currentAnnotation = this.get('uiState.models.annotation'); if (item === currentItem || item.get('orderedAnnotations').includes(currentAnnotation)) { const routing = this.get('routing'); routing.transitionTo('projects.project.spider.sample.data', [], {}, true); } item.deleteRecord(); this.saveAnnotationAndRelatedSelectors(item); }, removeAnnotation(annotation) { this.get('_removeAnnotationTask').perform(annotation); }, _removeAnnotationTask: task(function * (annotation) { const currentAnnotation = this.get('uiState.models.annotation'); if (annotation === currentAnnotation) { const routing = this.get('routing'); routing.transitionTo('projects.project.spider.sample.data', [], {}, true); } annotation.deleteRecord(); yield this.saveAnnotationAndRelatedSelectors(annotation); }).drop(), removeAnnotationExtractor(annotation, extractor) { annotation.get('extractors').removeObject(extractor); annotation.save(); }, removeFragment(startUrl, fragment) { startUrl.fragments.removeObject(fragment); }, selectAnnotation(annotation) { if (this.get('uiState.models.annotation') !== annotation) { const routing = this.get('routing'); routing.transitionTo('projects.project.spider.sample.data.annotation', [annotation], {}, true); } }, selectAnnotationElement(annotation, element, redirect = false) { this.set('uiState.viewPort.selectedElement', element); this.set('uiState.viewPort.originalSelectedElement', element); this.set('uiState.viewPort.selectedModel', annotation); if (redirect) { this.selectAnnotation(annotation); } }, clearSelection() { this.set('uiState.viewPort.selectedElement', null); this.set('uiState.viewPort.originalSelectedElement', null); const routing = this.get('routing'); const currentRouteName = routing.get('router.currentRouteName'); let nextRouteName; if (currentRouteName.startsWith('projects.project.spider.sample')) { nextRouteName = currentRouteName.split('.').slice(0, 5).join('.'); } else { nextRouteName = 'projects.project.spider.sample'; } routing.transitionTo(nextRouteName, [], {}, true); }, addElementToAnnotation(annotation, element) { annotation.addElement(element); this.saveAnnotationAndRelatedSelectors(annotation).then(() => { this.selectAnnotationElement(annotation, element); }); }, removeElementFromAnnotation(annotation, element) { annotation.removeElement(element); this.selectAnnotation(annotation); this.saveAnnotationAndRelatedSelectors(annotation); }, updateSampleSelectors(sample) { const selectorMatcher = this.get('selectorMatcher'); return createStructure(sample).then(structure => { updateStructureSelectors(structure, selectorMatcher); return null; }); } }); ================================================ FILE: portiaui/app/services/extracted-items.js ================================================ import Ember from 'ember'; const { computed } = Ember; import { task, timeout } from 'ember-concurrency'; const SECOND = 1000; const INITIAL_TIMEOUT = 2 * SECOND; const MAX_TIMEOUT = 30 * SECOND; export default Ember.Service.extend({ uiState: Ember.inject.service(), webSocket: Ember.inject.service(), items: [], links: {}, isExtracting: false, failedExtraction: false, extractionTimeout: 0, spider: computed.readOnly('uiState.models.spider'), sample: computed.readOnly('uiState.models.sample'), noSamples: computed.equal('spider.samples.length', 0), init() { this._super(); let ws = this.get('webSocket'); ws.addCommand('metadata', this, this._setItems); ws.addCommand('extract_items', this, this._setExtraction); }, activateExtraction() { this.set('items', []); this.set('extractionTimeout', 0); this.set('isExtracting', true); this.set('failedExtraction', false); this.get('_extract').cancelAll(); }, failExtraction(msg) { this._finishExtraction(); this.set('failedExtraction', true); this.set('failedExtractionMsg', msg); }, update() { Ember.run.throttle(this, this._getitems, 300, false); }, _getitems() { const spiderId = this.get('spider.id'); if (spiderId) { this.get('webSocket').send({ _command: 'extract_items', project: this.get('uiState.models.project.id'), spider: spiderId, sample: this.get('sample.id') }); } }, _setExtraction(data) { if (this.get('noSamples')) { this.failExtraction('Samples are needed for extracting data.'); return; } this._updateItems(data); this._updateExtraction(data); this._setItems(data); }, _extract: task(function * () { const t = this.get('extractionTimeout'); yield timeout(t); this.update(); this.set('extractionTimeout', (t === 0) ? INITIAL_TIMEOUT : t * 2); }).drop(), _setItems(data) { this._startExtraction(data); this.setProperties({ 'links': data.links, 'changes': data.changes, 'type': data.type, 'changed': data.changed }); }, _startExtraction(data) { if (data.loaded && this.get('isExtracting')) { this.get('_extract').perform(); } }, _updateItems(data) { const items = data.items; const newItems = items && items.length >= this.get('items.length'); if (newItems) { this.set('items', items); } }, _updateExtraction(data) { const receivedItems = data.items && data.items.length > 0; // Ensures the wait time is 254 seconds ~ 4 minutes const exceedWait = this.get('extractionTimeout') > MAX_TIMEOUT; if (receivedItems || exceedWait) { this._finishExtraction(); } else { this.get('_extract').perform(); } }, _finishExtraction() { this.set('isExtracting', false); this.get('_extract').cancelAll(); } }); ================================================ FILE: portiaui/app/services/notification-manager.js ================================================ import Ember from 'ember'; export default Ember.Service.extend({ banners: [], notifications: [], add(options) { /* properties: title (optional), message, type (optional): info (default), warning, success, danger */ return this.get('notifications').pushObject(options); }, addBanner(options) { return this.get('banners').addObject(options); }, removeBanner(options) { return this.get('banners').removeObject(options); }, showNotification(title, message, type) { if (title && !message) { message = title; title = null; } if (message) { this.add({ title, message, type: type || 'info' }); } }, showSuccessNotification(title, message) { this.showNotification(title, message, 'success'); }, showWarningNotification(title, message) { this.showNotification(title, message, 'warning'); }, showErrorNotification(title, message) { this.showNotification(title, message, 'danger'); } }); ================================================ FILE: portiaui/app/services/overlays.js ================================================ import Ember from 'ember'; export default Ember.Service.extend({ counter: 0, hasOverlays: Ember.computed.bool('counter'), add() { this.incrementProperty('counter'); }, remove() { this.decrementProperty('counter'); } }); ================================================ FILE: portiaui/app/services/position-monitor.js ================================================ import Ember from 'ember'; export default Ember.Service.extend({ elements: [], timerId: null, registerElement(element, context, readCallback, writeCallback) { const options = { element, context, readCallback, writeCallback, rects: null, boundingRect: null }; this.elements.push(options); if (this.timerId === null) { this.updateRaf(); } }, unRegisterElement(element, context, readCallback, writeCallback) { const elements = this.elements; const match = elements.find(options => options.element === element && options.context === context && options.readCallback === readCallback && options.writeCallback === writeCallback); if (match) { elements.removeObject(match); if (!elements.length) { cancelAnimationFrame(this.timerId); this.timerId = null; } } }, updateRaf() { if (this.timerId !== null) { cancelAnimationFrame(this.timerId); } this.update(); this.timerId = requestAnimationFrame(this.updateRaf.bind(this)); }, update(elements) { elements = Array.isArray(elements) ? elements : this.elements; const updates = []; // for performance first do DOM reads ... elements.forEach(options => { const {element, rects} = options; const newRects = element.getClientRects(); let changed = false; if (!rects || rects.length !== newRects.length) { changed = true; } else { for (let i = 0; i < rects.length; i++) { const rect = rects[i]; const newRect = newRects[i]; if (newRect.top !== rect.top || newRect.bottom !== rect.bottom || newRect.left !== rect.left || newRect.right !== rect.right) { changed = true; break; } } } if (changed) { options.rects = newRects; options.boundingRect = element.getBoundingClientRect(); updates.push(options); } }); // ... then run callbacks which will perform additional DOM reads ... updates.forEach(({element, context, readCallback, rects, boundingRect}) => { if (readCallback) { readCallback.call(context, rects, boundingRect, element); } }); // ... then run callbacks which will perform DOM writes updates.forEach(({element, context, writeCallback, rects, boundingRect}) => { writeCallback.call(context, rects, boundingRect, element); }); } }); ================================================ FILE: portiaui/app/services/saving-notification.js ================================================ import Ember from 'ember'; const { computed, inject: { service } } = Ember; export default Ember.Service.extend({ extractedItems: service(), counter: 0, lastSaved: null, isSaving: computed.bool('counter'), start() { this.get('extractedItems').activateExtraction(); this.incrementProperty('counter'); }, end() { this.decrementProperty('counter'); const counter = this.get('counter'); if (!counter) { this.set('lastSaved', new Date()); } this.get('extractedItems').update(); } }); ================================================ FILE: portiaui/app/services/selector-matcher.js ================================================ import Ember from 'ember'; function nodesEqual(nodesA, nodesB) { if (nodesA.length !== nodesB.length) { return false; } for (let i = nodesA.length; i--;) { if (nodesA[i] !== nodesB[i]) { return false; } } return true; } export default Ember.Service.extend(Ember.Evented, { browser: Ember.inject.service(), selectors: new Map(), timerId: null, updateInterval: 100, register(selector, target, method) { const elements = this.selectors.get(selector); if (elements) { if (method) { method.call(target, elements); } else { target(elements); } } else { this.selectors.set(selector, []); } if (this.timerId === null) { this.scheduleUpdate(1); } this.on(...arguments); }, unRegister(selector) { this.off(...arguments); if (!this.has(selector)) { this.selectors.delete(selector); if (!this.selectors.size) { Ember.run.cancel(this.timerId); this.timerId = null; } } }, watch(target, method) { this.on('changed', target, method); }, unWatch(target, method) { this.off('changed', target, method); }, query(selector) { const $document = this.get('browser.$document'); if ($document) { let elements = this.selectors.get(selector); if (!elements) { return $document.find(selector).toArray(); } else if (!elements.length) { elements = $document.find(selector).toArray(); this.selectors.set(selector, elements); } return elements; } else { return []; } }, scheduleUpdate(delay) { Ember.run.cancel(this.timerId); this.timerId = Ember.run.later(this, this.update, delay); }, update() { const $document = this.get('browser.$document'); if ($document) { const updates = []; this.selectors.forEach((currentElements, selector) => { const newElements = $document.find(selector).toArray(); if (!nodesEqual(currentElements, newElements)) { this.selectors.set(selector, newElements); updates.push([selector, newElements]); } }); if (updates.length) { updates.forEach(([selector, elements]) => { this.trigger(selector, elements); }); this.trigger('changed', updates); } } this.scheduleUpdate(this.updateInterval); } }); ================================================ FILE: portiaui/app/services/store.js ================================================ import DS from 'ember-data'; export default DS.Store.extend({ didSaveRecord(internalModel, dataArg) { // update record id if data has different id // TODO: support rollback of id change const recordMap = this.typeMapFor(internalModel.type).idToRecord; if (internalModel.id !== null && !(internalModel.id in recordMap)) { for (let id of Object.keys(recordMap)) { if (recordMap[id] === internalModel) { delete recordMap[id]; recordMap[internalModel.id] = internalModel; } } } if (dataArg && dataArg.data && dataArg.data.links) { this.updateRecordLinks(internalModel, dataArg.data.links); } return this._super(...arguments); }, _load(data) { const internalModel = this._super(...arguments); this.updateRecordLinks(internalModel, data.links); return internalModel; }, updateRecordLinks(internalModel, links) { internalModel._links = links || internalModel._links || {}; } }); ================================================ FILE: portiaui/app/services/ui-state.js ================================================ import Ember from 'ember'; import { storageFor } from 'ember-local-storage'; function computedActiveRoutes(mapping) { const properties = Object.keys(mapping); return Ember.computed( 'router.currentState', ...properties.map(key => mapping[key]), function() { const activeRoutes = {}; const currentRouteName = this.get('router.currentRouteName'); properties.forEach(property => { const routeProperty = mapping[property]; const routeName = this.get(`${routeProperty}.routeName`); activeRoutes[property] = currentRouteName.startsWith(routeName); }); return activeRoutes; }); } function computedRouteModels(mapping) { const properties = Object.keys(mapping); return Ember.computed( 'router.currentState', ...properties.map(key => mapping[key]), function() { const models = {}; const currentRouteName = this.get('router.currentRouteName'); properties.forEach(property => { const routeProperty = mapping[property]; const routeName = this.get(`${routeProperty}.routeName`); const startsWithRoute = currentRouteName && currentRouteName.startsWith(routeName); models[property] = startsWithRoute ? this.get(routeProperty).modelFor(routeName) : null; }); return models; }); } export default Ember.Service.extend({ models: computedRouteModels({ project: 'projectRoute', spider: 'spiderRoute', sample: 'sampleRoute', item: 'itemRoute', annotation: 'annotationRoute', schema: 'schemaRoute', field: 'fieldRoute' }), routes: computedActiveRoutes({ project: 'projectRoute', spider: 'spiderRoute', sample: 'sampleRoute', data: 'dataRoute', item: 'itemRoute', annotation: 'annotationRoute', schema: 'schemaRoute', field: 'fieldRoute' }), slideMain: false, selectedTools: storageFor('uiStateSelectedTools'), collapsedPanels: storageFor('uiStateCollapsedPanels'), viewPort: { hoveredElement: null, hoveredModels: [], // When the selected element is changed by clicking a parent in // the inspector, this is the original element that was selected originalSelectedElement: null, selectedElement: null, selectedModel: null, hoverOverlayColor: null } }); ================================================ FILE: portiaui/app/services/web-socket.js ================================================ import Ember from 'ember'; import config from '../config/environment'; import { logError, shortGuid } from '../utils/utils'; const { computed, run, Evented, Logger, RSVP, Service} = Ember; const APPLICATION_UNLOADING_CODE = 4001; const DEFAULT_RECONNECT_TIMEOUT = 5000; const DEFAULT_MAX_RECONNECT_TIMEOUT = 60000; var defaultUrl = function() { var uri = URI.parse(config.SLYD_URL || window.location.protocol + '//' + window.location.host); if (!/wss?/.test(uri.protocol)) { uri.protocol = uri.protocol === 'https' ? 'wss' : 'ws'; } uri.path = '/ws'; return URI.build(uri); }; export default Service.extend(Evented, { closed: true, opened: computed.not('closed'), connecting: false, ws: null, heartbeat: null, nextConnect: null, reconnectTimeout: DEFAULT_RECONNECT_TIMEOUT, deferreds: {}, url: defaultUrl(), secondsUntilReconnect: 0, reconnectImminent: computed('reconnectMessage', 'secondsUntilReconnect', function() { return this.get('secondsUntilReconnect') < 2 && this.get('reconnectMessage').length === 0; }), reconnectComponent: null, reconnectMessage: '', showBanner: computed.or('closed', 'reconnectComponent'), init: function(options) { if(options) { this.setProperties(options); } window.addEventListener('beforeunload', () => { if(this.get('opened')) { this.close(APPLICATION_UNLOADING_CODE); } }); }, connect: function() { if(this.get('closed')) { return this._createWebsocket(); } }, _updateCountdownTimer: function() { if(this.secondsUntilReconnect === 0 && this.get('countdownTid')) { clearInterval(this.get('countdownTid')); this.set('countdownTid', null); } else if (this.secondsUntilReconnect > 0 && !this.get('countdownTid')) { this.set('countdownTid', setInterval(() => { this.decrementProperty('secondsUntilReconnect'); }, 1000)); } }.observes('secondsUntilReconnect'), _onclose(e) { if (this.heartbeat) { clearInterval(this.heartbeat); } this.set('closed', true); this.set('connecting', false); Logger.log(''); if(e.code !== APPLICATION_UNLOADING_CODE && e.code !== 1000) { if (!window.navigator.onLine) { this.set('reconnectMessage', 'You are currently offline, you will be reconnected as soon as possible, or '); window.addEventListener('online', this.connect, false); return; } var timeout = this._connectTimeout(); this.set('secondsUntilReconnect', Math.round(timeout/1000)); var next = run.later(this, this.connect, timeout); this.set('reconnectTid', next); } }, _onmessage({data}) { try { data = JSON.parse(data); } catch (err) { return logError('Error parsing data returned by server: ' + err + '\n' + data); } var command = data._command; if (!command) { return logError('Received response with no command: ' + JSON.stringify(data)); } var deferred = data.id; if (deferred in this.get('deferreds')) { deferred = this.get('deferreds.' + deferred); delete this.get('deferreds')[data.id]; if (data.error) { var err = new Error(data.reason); err.reason = {jqXHR: {responseText: data.reason}}; deferred.reject(err); throw err; } else { deferred.resolve(data); } } if (this.has(command)) { this.trigger(command, data); } else { return Logger.debug('Received unknown command: ' + command); } }, _onopen() { Logger.log(''); this.set('closed', false); this.set('reconnectMessage', ''); this.set('connecting', false); this.set('reconnectTimeout', DEFAULT_RECONNECT_TIMEOUT); this.heartbeat = setInterval(function() { this.send({_command: 'heartbeat'}); }.bind(this), 20000); window.removeEventListener('online', this.connect, false); }, _createWebsocket: function() { if (this.get('reconnectTid')) { run.cancel(this.get('reconnectTid')); this.set('reconnectTid', null); } this.set('secondsUntilReconnect', 0); this.set('connecting', true); var ws; try { ws = new WebSocket(this.get('url')); } catch (err) { Logger.log('Error connecting to server: ' + err); this.set('connecting', false); return; } ws.onclose = this._onclose.bind(this); ws.onmessage = this._onmessage.bind(this); ws.onopen = this._onopen.bind(this); this.set('ws', ws); }, _connectTimeout: function() { var timeout = Math.max(this.get('reconnectTimeout'), DEFAULT_RECONNECT_TIMEOUT); this.set('reconnectTimeout', Math.min(timeout*2, DEFAULT_MAX_RECONNECT_TIMEOUT)); return this.get('reconnectTimeout'); }, addCommand: function(/*command, target, method*/) { this.on(...arguments); }, removeCommand: function(/*command, target, method*/) { this.off(...arguments); }, close:function(code, reason) { code = code || 1000; reason = reason || 'application called close'; return this.get('ws').close(code, reason); }, send: function(data) { if (!this.get('closed') && data) { if (typeof data !== 'string') { try { data = JSON.stringify(data); } catch (err) { return logError('Error serializing data: ' + err); } } return this.get('ws').send(data); } }, _sendPromise: function(data) { var deferred = new RSVP.defer(); if (!data._meta) { data._meta = this._metadata(null); } else if (!data._meta.id) { data._meta.id = shortGuid(); } if(this.get('opened')) { this.set(`deferreds.${data._meta.id}`, deferred); this.send(data); } else { deferred.reject('Websocket is closed'); } return deferred.promise; }, _metadata: function(type) { return { // TODO: send current spider and project? type: type, id: shortGuid() }; } }); ================================================ FILE: portiaui/app/storages/cookies.js ================================================ import StorageObject from 'ember-local-storage/local/object'; export default StorageObject.extend(); ================================================ FILE: portiaui/app/storages/page-loads.js ================================================ import StorageObject from 'ember-local-storage/local/object'; export default StorageObject.extend(); ================================================ FILE: portiaui/app/storages/ui-state-collapsed-panels.js ================================================ import StorageObject from 'ember-local-storage/local/object'; export default StorageObject.extend(); ================================================ FILE: portiaui/app/storages/ui-state-selected-tools.js ================================================ import StorageObject from 'ember-local-storage/local/object'; const ToolStorage = StorageObject.extend({ init() { this._super(...arguments); // clear the next click selection mode if magic tool is active if (this.get('magicToolActive')) { this.set('selectionMode', null); } } }); ToolStorage.reopenClass({ initialState() { return { magicToolActive: true, selectionMode: null }; } }); export default ToolStorage; ================================================ FILE: portiaui/app/styles/_animations.scss ================================================ @keyframes fadeOut { 99% { display: block; opacity: 0; } } @keyframes hideDelay { from { display: inherit; } 99% { display: inherit; } to { display: none; } } ================================================ FILE: portiaui/app/styles/_bootstrap_overrides.scss ================================================ @mixin tab-focus() { /* // Default outline: thin dotted; // WebKit outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; */ outline: 0; } @mixin button-variant($color, $background, $border) { color: $color; background-color: $background; border-color: $border; /* &:focus, &.focus { color: $color; background-color: darken($background, 10%); border-color: darken($border, 25%); } */ &:hover { color: $color; background-color: darken($background, 10%); border-color: darken($border, 12%); } &:active, &.active, .open > &.dropdown-toggle { color: $color; background-color: darken($background, 10%); border-color: darken($border, 12%); &:hover, &:focus, &.focus { color: $color; background-color: darken($background, 17%); border-color: darken($border, 25%); } } &:active, &.active, .open > &.dropdown-toggle { background-image: none; } &.disabled, &[disabled], fieldset[disabled] & { //&:hover, //&:focus, //&.focus { &:hover { background-color: $background; border-color: $border; } } .badge { color: $background; background-color: $color; } } ================================================ FILE: portiaui/app/styles/_icons.scss ================================================ .portia-icon { display: inline-block; line-height: 1; font-style: normal; font-variant: normal; font-weight: normal; font-size: inherit; // can't have font-size inherit on line above, so need to override text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @function encode-leading-hash($string) { @if str-slice($string, 1, 1) == '#' { $string: '%23' + str-slice($string, 2); } @return $string; } @function portia-spider-icon($foreground-color, $background-color) { $foreground-color: encode-leading-hash(unquote($foreground-color)); $background-color: encode-leading-hash(unquote($background-color)); @return 'data:image/svg+xml,'; } .portia-icon-spider { &:before { content: ''; display: inline-block; height: 14px; width: 19px; text-align: center; vertical-align: middle; background: transparent url(portia-spider-icon('#777', ''+$sidebar-background-color)) no-repeat center; } .btn-primary & { &:before { background-image: url(portia-spider-icon(''+$btn-primary-color, ''+$btn-primary-bg)); } } #side-bar h2 > & { &:before { background-image: url(portia-spider-icon(''+$list-heading-color, ''+$sidebar-background-color)); } } } .portia-icon-number, .portia-icon-regex, .portia-icon-text { position: relative; &:before { display: inline-block; font-weight: bold; transform: scaleX(0.5); position: absolute; left: -1000%; right: -1000%; text-align: center; } &:after { content: ' '; white-space: pre; } } .portia-icon-number { width: 1.7ch; &:before { content: '123'; } } .portia-icon-regex { width: 2.1ch; &:before { content: '\\d*'; transform: scaleX(0.8); } } .portia-icon-text { width: 2.1ch; &:before { content: 'ABC'; } } %combined-icon { position: relative; &:after { display: inline-block; position: absolute; width: 100%; text-align: center; vertical-align: middle; } } .portia-icon-safe-html { @extend .#{$fa-css-prefix}; @extend %combined-icon; @extend .#{$fa-css-prefix}-code; &:before { display: inline-block; transform: scale(0.8); } &:after { content: $fa-var-circle-thin; left: 0; transform: scale(1.2); } } .portia-icon-selector { @extend .#{$fa-css-prefix}; @extend %combined-icon; @extend .#{$fa-css-prefix}-circle; &:after { content: $fa-var-mouse-pointer; left: 1px; top: -1px; color: $fa-inverse; transform: scale(0.6); } } %subscript-icon { @extend %combined-icon; &:after { right: -3px; bottom: -3px; transform: scale(0.7); text-shadow: -1px -1px 1px $sidebar-background-color, 1px 1px 1px $sidebar-background-color, -1px 1px 1px $sidebar-background-color, 1px -1px 1px $sidebar-background-color; } } .portia-icon-generated-url { @extend .#{$fa-css-prefix}; @extend %subscript-icon; @extend .#{$fa-css-prefix}-globe; &:after { content: $fa-var-tasks; } } .portia-icon-feed-url { @extend .#{$fa-css-prefix}; @extend %subscript-icon; @extend .#{$fa-css-prefix}-globe; &:after { content: $fa-var-rss; } } ================================================ FILE: portiaui/app/styles/_lib_config.scss ================================================ $animation-time: .15s; $animation-easing: ease-in-out; $animation-easing-in: ease-in; $animation-easing-out: ease-out; // font awesome settings $fa-font-path: 'fonts'; ================================================ FILE: portiaui/app/styles/_variables.scss ================================================ // sidebar $sidebar-width: 331px; // tree list $tree-list-row-height: 30px !default; $tree-list-icon-width: $tree-list-row-height !default; // panels $sidebar-background-color: $navbar-default-bg; $panel-padding-y: 10px; $panel-content-min-height: $tree-list-row-height * 3; $panel-min-height: $panel-content-min-height + $panel-padding-y * 2; // typography $space-width: 0.285em; // icons $pip-size: 3px; $icon-fade-opacity: 0.25; // colors $list-heading-color: $brand-danger; $pip-color: $panel-default-border; $panel-bg: darken($navbar-default-bg, 1.5%); $light-gray: #999; ================================================ FILE: portiaui/app/styles/app.scss ================================================ @import "lib_config"; // Bootstrap @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/variables"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/mixins"; @import "bootstrap_overrides"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/normalize"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/print"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/glyphicons"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/scaffolding"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/type"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/code"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/grid"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tables"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/forms"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/buttons"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/component-animations"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/dropdowns"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/button-groups"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/input-groups"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/navs"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/navbar"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/breadcrumbs"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/pagination"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/pager"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/labels"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/badges"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/jumbotron"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/thumbnails"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/alerts"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/progress-bars"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/media"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/list-group"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/panels"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/wells"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/close"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/modals"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tooltip"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/popovers"; //@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/carousel"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/utilities"; @import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/responsive-utilities"; @import "bower_components/font-awesome/scss/font-awesome"; @import "variables"; @import "generic"; @import "document"; @import "animations"; @import "icons"; @import "droplet"; @import "layout/clickable"; @import "layout/forms"; @import "layout/full-page-content"; @import "templates/application"; @import "templates/projects"; @import "templates/browsers"; @import "components/animation-container"; @import "components/browser-iframe"; @import "components/browser-view-port"; @import "components/combo-box"; @import "components/dropdown-menu"; @import "components/dropdown-widget"; @import "components/extracted-item-table"; @import "components/extracted-items-json-panel"; @import "components/extractor-options"; @import "components/help-icon"; @import "components/icon-button"; @import "components/input-with-clear"; @import "components/inspector-panel"; @import "components/list-item-badge"; @import "components/list-item-combo"; @import "components/list-item-editable"; @import "components/list-item-icon"; @import "components/list-item-selectable"; @import "components/list-item-text"; @import "components/notifications"; @import "components/regex-pattern-list"; @import "components/save-status"; @import "components/select-box"; @import "components/side-bar"; @import "components/sliding-main"; @import "components/show-links-legend"; @import "components/tool-group"; @import "components/tool-panel"; @import "components/tooltip-container"; @import "components/top-bar"; @import "components/tree-list"; @import "components/url-bar"; @import "components/page-actions"; @import "components/conflicts"; @import "components/start-url-options"; @import "components/fragment-options"; @import "components/project-structure-spider-generation-url"; @import "components/indentation-spacer"; @import "components/dropdown-delete"; ================================================ FILE: portiaui/app/styles/components/animation-container.scss ================================================ .animation-container { opacity: 1; overflow: visible; transition: opacity $animation-time $animation-easing $animation-time; &.inline { display: inline-block; } &.fade { opacity: 0; transition-delay: 0s; pointer-events: none; } } .animation-content { position: absolute; top: 0; left: 0; &[style^="transform"] { transition: transform $animation-time $animation-easing; } } ================================================ FILE: portiaui/app/styles/components/browser-iframe.scss ================================================ .browser-iframe { filter: none; opacity: 1; transition: filter ($animation-time * 2) $animation-easing, opacity ($animation-time * 2) $animation-easing; &.has-overlays { opacity: .5; @supports (filter: grayscale(100%)) { filter: grayscale(100%); opacity: 1; } } } ================================================ FILE: portiaui/app/styles/components/browser-view-port.scss ================================================ .browser-view-port { position: relative; flex: 1 1 auto; display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; margin: $grid-gutter-width; } .browser-start-page { @extend .full-page-content; position: absolute; top: -$grid-gutter-width; bottom: -$grid-gutter-width; left: -$grid-gutter-width; right: -$grid-gutter-width; opacity: 1; background-color: #fff; transition: opacity $animation-time $animation-easing-out; z-index: 2; &.hide { display: flex !important; pointer-events: none; opacity: 0; } form { width: 50%; margin: 2em auto; } .btn { display: none; } } $panel-heading-vertical-padding: nth($panel-heading-padding, 1); $panel-heading-horizontal-padding: nth($panel-heading-padding, 2); .browser-navigation { flex: 0 0 auto; display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: center; padding: ($panel-heading-vertical-padding / 2) ($panel-heading-horizontal-padding / 2); z-index: 1; .btn { line-height: $line-height-computed; } .navbar-form { padding: 0; flex: 1 1 auto; } .browser-toolbar { flex: 0 1 auto; display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: center; margin: 0; } } .browser-navigation, .browser-toolbar { > * { flex: 0 0 auto; margin: ($panel-heading-vertical-padding / 2) ($panel-heading-horizontal-padding / 2); } } .browser-banner { $browser-banner-height: $line-height-computed + $alert-padding * 2; @extend .alert; @extend .alert-warning; flex: 0 0 auto; height: $browser-banner-height; margin-bottom: 0; border-radius: 0; border-top: none; border-left: none; border-right: none; margin-top: 0; transition: margin-top $animation-time $animation-easing; &.hide { display: block !important; margin-top: -$browser-banner-height; } } .frame-container { flex: 1 1 auto; overflow: hidden; display: flex; position: relative; flex-direction: row; flex-wrap: nowrap; align-items: stretch; padding: 0; @include border-bottom-radius($panel-border-radius - 1); iframe { width: 100%; border: none; flex: 1 1 auto; overflow: auto; } } .overlay-container { position: absolute; top: 0; left: 0; pointer-events: none; } .overlay-box { position: relative; display: flex; justify-content: center; align-items: center; width: 100%; height: 100%; transition: box-shadow $animation-time $animation-easing; z-index: 0; } .overlay-box-background { position: absolute; top: 0; bottom: 0; left: 0; right: 0; opacity: 0.15; border-radius: 2px; transition: opacity ($animation-time / 2) $animation-easing-in, background-color $animation-time $animation-easing; } .overlay-icon { color: #fff; opacity: 0.8; z-index: 1; transition: opacity ($animation-time / 2) $animation-easing-in ($animation-time / 2), text-shadow $animation-time $animation-easing; &.hide { display: inline; opacity: 0; } } .overlay { position: absolute; top: 0; left: 0; z-index: 1; transition: opacity ($animation-time / 2) $animation-easing-in; &.group-hovered, &.group-selected, .none-hovered.none-selected:not(.group-hovered):not(.group-selected) & { .overlay-box-background { opacity: 0.45; } } &.hovered, &.selected, .none-hovered &.group-hovered, .none-selected &.group-selected { .overlay-box-background { opacity: 0.8; } } &.hovered.mode-add { .overlay-box-background { opacity: 0.65; } } .browser-view-port:not(.none-selected) & { &.hovered.mode-edit { .overlay-box-background { opacity: 0.65; } } } &.hovered, &.group-hovered { z-index: 1; } &.selected, &.group-selected { z-index: 2; } } .hover-overlay { z-index: 3; transition: opacity $animation-time $animation-easing, top 100ms $animation-easing-out, bottom 100ms $animation-easing-out, left 100ms $animation-easing-out, right 100ms $animation-easing-out; &.hide { display: block !important; opacity: 0; .overlay-icon { display: none; } } .overlay-box-background { opacity: 0.65; } } ================================================ FILE: portiaui/app/styles/components/combo-box.scss ================================================ .combo-box { .combo-input { display: inline-flex; flex-direction: row; flex-wrap: nowrap; align-items: stretch; justify-content: space-between; text-align: left; color: $input-color !important; $caret-container-width: ($caret-width-base + $padding-base-horizontal) * 2 + 1px; input { padding-right: $caret-container-width - 1px; } .caret-container { display: inline-flex; align-items: center; justify-content: center; width: $caret-container-width; margin-left: -$caret-container-width; cursor: pointer; } .caret { margin: 0; margin-right: 1px; } } &:not(.open) { input { cursor: pointer; } .caret-container { pointer-events: none; } } } ================================================ FILE: portiaui/app/styles/components/conflicts.scss ================================================ .topbar-conflicts { margin-top: 7px; } .conflicts-text { padding: 100px; } ================================================ FILE: portiaui/app/styles/components/dropdown-delete.scss ================================================ li.dropdown-delete { cursor: pointer; a { color: $brand-danger; &:hover { color: $brand-danger; } } &.is-confirmed { background-color: $brand-danger; a { color: white; &:hover { background-color: $brand-danger; color: white; } } } } ================================================ FILE: portiaui/app/styles/components/dropdown-menu.scss ================================================ .dropdown-menu { outline: 0; margin: 2px 0; max-height: 200px; overflow-y: scroll; > .focused:not(.active) > a { &, &:hover, &:focus { text-decoration: none; color: $dropdown-link-hover-color; background-color: $dropdown-link-hover-bg; } } .icon { display: inline-block; width: $tree-list-icon-width; height: $line-height-computed; margin-left: -6px; margin-right: 10px; line-height: $line-height-computed; text-align: center; vertical-align: middle; } } ================================================ FILE: portiaui/app/styles/components/dropdown-widget.scss ================================================ .dropdown-menu-floating { display: none; &.open { display: block; } } ================================================ FILE: portiaui/app/styles/components/extracted-item-table.scss ================================================ .extracted-item-table { user-select: text; &, table { margin-bottom: $line-height-computed; &:last-of-type { margin-bottom: 0; } &:not(:last-of-type) > tr, tr:not(:last-of-type) { > td { > table { &:last-of-type { margin-bottom: $line-height-computed; } } } } } table { margin-left: 20px; &:first-of-type { margin-top: $line-height-computed; } &:not(.extracted-item-table):not(:last-of-type) { margin-bottom: 0; } } td { vertical-align: top; color: $text-color; &:not(:last-child) { padding-right: ($grid-gutter-width / 2); color: $text-muted; } } } ================================================ FILE: portiaui/app/styles/components/extracted-items-json-panel.scss ================================================ .extracted-items-json { padding: (($line-height-computed - 1) / 2); margin: 0; font-family: $font-family-monospace; font-size: ($font-size-base - 1); // 14px to 13px line-height: $line-height-base; color: $text-muted; unicode-bidi: embed; word-break: break-all; word-wrap: break-word; user-select: text; b { font-weight: normal; display: inline-block; white-space: pre; float: left; word-spacing: 0px; &.open-container { white-space: normal; } &.new-line { width: 100%; } } } .json-value { white-space: normal; word-break: normal; display: inline-block; color: $text-color; float: left; text-indent: -1ch; margin: 0 0 0 1ch; } .json-key { white-space: pre; display: inline-block; float:left; } .json-array-spacing { white-space: pre; } .json-character-size { position: fixed; top: -10000px; } ================================================ FILE: portiaui/app/styles/components/extractor-options.scss ================================================ .extractor-options { &.tree-list { > .tree-list-item { > .tree-list-item-row { margin-top: $line-height-computed; margin-bottom: ($line-height-computed / 2); } > .tree-list { padding-left: 0; } } } } ================================================ FILE: portiaui/app/styles/components/fragment-options.scss ================================================ form.fragment-form { margin-bottom: 10px; } .fragment-form { .compact-control { padding-left: 8px; padding-right: 8px; } .fragment-input { width: 125px; margin-left: 8px; margin-right: 10px; } .fragment-type { width: 75px; .value { max-width: calc(100% - 10px); } } .fragment-left-half { width: 52px; margin-left: 8px; margin-right: 4px; } .fragment-right-half { width: 52px; margin-left: 4px; margin-right: 8px; } } .fragment-action-icon { position: absolute; right: -10px; line-height: 35px; } .fragment-error { margin: 0 4px 0 4px; } ================================================ FILE: portiaui/app/styles/components/help-icon.scss ================================================ .icon-button { &.help-icon { pointer-events: auto; } } ================================================ FILE: portiaui/app/styles/components/icon-button.scss ================================================ .icon-button { line-height: inherit; text-align: center; outline: 0; pointer-events: none; transition: opacity $animation-time $animation-easing, color $animation-time $animation-easing; .dropdown-menu & { transition: 0s; } &.has-action { pointer-events: auto; cursor: pointer; } &.disabled { color: $navbar-default-color !important; cursor: not-allowed; } .dropdown-menu .disabled & { color: $dropdown-link-disabled-color !important; cursor: not-allowed; } } .structure-list-details { opacity: $icon-fade-opacity; pointer-events: inherit; &:hover, .active > & { opacity: 1; } } .structure-list-add, .structure-list-play, .structure-list-publish { color: $brand-success !important; } .structure-list-discard, .structure-list-error, .structure-list-remove { color: $brand-danger !important; } .structure-list-warning { color: $brand-warning !important; } .icon-button-help { color: $brand-info !important; } ================================================ FILE: portiaui/app/styles/components/indentation-spacer.scss ================================================ .indentation-spacer { display: inline-block; min-width: 20px; &.is-small { width: 10px; } } ================================================ FILE: portiaui/app/styles/components/input-with-clear.scss ================================================ .input-with-clear { input { padding-right: 34px; } } .clear-input { position: absolute; right: 11px; top: 0; bottom: 0; height: 14px; line-height: 14px; margin: auto; color: #ccc; z-index: 3; } ================================================ FILE: portiaui/app/styles/components/inspector-panel.scss ================================================ .inspector { $inspector-line-padding-y: ($tree-list-row-height - $line-height-computed) / 2; overflow: hidden; .path-item { border-radius: 5px; padding: 0 3px; font-size: 0.9em; font-family: monospace; } .path-selected { background-color: #337AB7; color: #fff; } table { width: 100%; } tr { cursor: pointer; } > div > div, td { padding: $inspector-line-padding-y 0; } td { vertical-align: top; color: $text-color; &:first-child { padding-right: ($grid-gutter-width / 2); color: $text-muted; white-space: nowrap; } &:last-child { position: relative; width: 100%; } > div { display: flex; flex-direction: row; flex-wrap: nowrap; > div { &:first-child { flex: 1 1 auto; position: relative; } &:last-child { padding-left: $line-height-computed; } } } .value { position: absolute; left: 0; right: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } } .structure-list-add { opacity: 1; text-align: right; } .empty-notice { height: $panel-content-min-height; line-height: $panel-content-min-height; margin: 0; padding: 0; text-align: center; vertical-align: middle; } } ================================================ FILE: portiaui/app/styles/components/list-item-badge.scss ================================================ .list-item-badge { display: inline-block; flex: 0 0 20px; text-align: center; .badge { vertical-align: baseline; max-width: 26px; transition: background-color $animation-time $animation-easing; } .badge-centered { display: inline-block; margin: 0 -1000%; white-space: nowrap; } } ================================================ FILE: portiaui/app/styles/components/list-item-combo.scss ================================================ .list-item-combo { flex: 1 1 auto; min-width: 0; .list-item-editable + &, & + & { flex-grow: 0; } } ================================================ FILE: portiaui/app/styles/components/list-item-editable.scss ================================================ .list-item-editable { display: inline-flex; flex-direction: row; flex-wrap: nowrap; align-items: center; flex: 1 1 auto; min-width: 90px; margin-left: 5px; > span { flex: 0 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .fa-pencil { flex: 0 0 $tree-list-icon-width; color: $navbar-default-color; cursor: pointer; opacity: $icon-fade-opacity; transition: opacity $animation-time $animation-easing; text-align: center; } &:hover { .fa-pencil { opacity: 1; } } input { flex: 1 1 100%; } } ================================================ FILE: portiaui/app/styles/components/list-item-icon.scss ================================================ .list-item-icon { width: $tree-list-icon-width; flex: 0 0 $tree-list-icon-width; &.has-action { opacity: $icon-fade-opacity; &.active, .dropdown.open &, &:hover:not(.disabled) { opacity: 1; } } .tree-list-item-content & { height: $tree-list-row-height; line-height: $tree-list-row-height; } .tree-list-item-content a & { color: $navbar-default-color; } } ================================================ FILE: portiaui/app/styles/components/list-item-selectable.scss ================================================ .list-item-selectable { display: inline-flex; flex-direction: row; flex-wrap: nowrap; align-items: center; flex: 0 1 auto; .list-item-icon + &, .list-item-badge + & { flex-grow: 1; } &:not(.selecting) { > span { flex: 0 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .caret { flex: 0 0 auto; margin: 0 (($tree-list-icon-width - 8px) / 2); color: $navbar-default-color; opacity: $icon-fade-opacity; } &:hover { .caret { opacity: 1; } } } .select-box { min-width: 60px; } } ================================================ FILE: portiaui/app/styles/components/list-item-text.scss ================================================ .list-item-text { display: inline; flex: 1 1 auto; padding: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; &.title { text-transform: uppercase; } } ================================================ FILE: portiaui/app/styles/components/notifications.scss ================================================ .notifications { $notification-top: $grid-gutter-width / 2; position: absolute; top: $notification-top; width: 100%; pointer-events: none; z-index: 3; .notification { margin-left: auto; margin-right: auto; max-width: 800px; &:first-of-type { margin-top: -15px; border-top: none; border-top-left-radius: 0; border-top-right-radius: 0; } > button { pointer-events: auto; outline: 0; } } } ================================================ FILE: portiaui/app/styles/components/page-actions.scss ================================================ ================================================ FILE: portiaui/app/styles/components/project-structure-spider-generation-url.scss ================================================ .generated-url { color: $navbar-default-color; margin-left: $space-width; } ================================================ FILE: portiaui/app/styles/components/regex-pattern-list.scss ================================================ .regex-pattern-list { .new-pattern { > div { display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; } i { width: $tree-list-row-height; flex: 0 0 $tree-list-row-height; height: $tree-list-row-height; line-height: $tree-list-row-height; text-align: center; } } } ================================================ FILE: portiaui/app/styles/components/save-status.scss ================================================ @keyframes saving-blink { 0% { opacity: .2; } 50% { opacity: 1; } 100% { opacity: .2; } } .save-status { .label { display: inline-block; min-width: 60%; cursor: default; transition: background-color ($animation-time * 2) $animation-easing; span { animation-name: saving-blink; animation-duration: 1.4s; animation-iteration-count: infinite; animation-fill-mode: both; &:nth-child(2) { animation-delay: .2s; } &:nth-child(3) { animation-delay: .4s; } } } } ================================================ FILE: portiaui/app/styles/components/select-box.scss ================================================ .select-box { .btn-default { text-align: left; color: $input-color !important; background-color: $input-bg !important; .value { float: left; max-width: calc(100% - 20px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .caret { float: right; margin: (($line-height-computed - $caret-width-base) / 2) 0; } } &.open { .btn-default { border-color: $input-border-focus !important; $color-rgba: rgba(red($input-border-focus), green($input-border-focus), blue($input-border-focus), .6); @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba !important); } } &:not(.open) { .btn-default { &:focus { @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); } } } } ================================================ FILE: portiaui/app/styles/components/show-links-legend.scss ================================================ #show-links-legend { .list-item-badge { margin-right: $space-width; } } ================================================ FILE: portiaui/app/styles/components/side-bar.scss ================================================ #side-bar { width: $sidebar-width; flex: 0 0 auto; background-color: $sidebar-background-color; border-right: 1px solid $navbar-default-border; padding: $navbar-padding-horizontal $navbar-padding-horizontal ($navbar-padding-horizontal + 10px); overflow-y: auto; overflow-x: hidden; z-index: 1; > div { position: relative; > .tree-list { margin-bottom: ($tree-list-row-height / 2); &:last-child { margin-bottom: 0; } > .animation-content { > .tree-list-item { > .animation-content { > .tree-list { > .animation-content { width: 100%; } } } } } } } .title { display: flex; line-height: $tree-list-row-height; .help-icon { margin-left: $space-width; } .animation-container { &.inline { vertical-align: bottom; } } } .icon { &.animation-container { flex: 0 0 auto; width: $tree-list-icon-width; height: $tree-list-row-height; } a { display: inline-block; } } .help { .tree-list-item-row { height: auto; } .alert { @extend .small; @extend .text-justify; margin: 0; width: 100%; } } .project-listing { justify-content: space-between; } .project-changes { text-transform: none; } } #options-panels, #tool-panels { flex: 0 0 auto; display: flex; flex-direction: column; flex-wrap: nowrap; justify-content: flex-start; align-items: stretch; width: $sidebar-width - $grid-gutter-width; transition: opacity $animation-time $animation-easing; &:after { content: ''; flex: 0.0000001 1 auto; background-color: $panel-bg; } } #tool-panels { margin-right: $grid-gutter-width; main & { opacity: 1; transition-delay: $animation-time; } main.slide-right & { opacity: 0; transition-delay: 0s; } } #options-panels { z-index: -1; margin-left: $grid-gutter-width - $sidebar-width; main & { opacity: 0; transition-delay: 0s; } main.slide-right & { opacity: 1; transition-delay: $animation-time; } } ================================================ FILE: portiaui/app/styles/components/sliding-main.scss ================================================ #window { overflow: hidden; } main { transition: transform $animation-time $animation-easing; transform: none; &.slide-right { transform: translateX($sidebar-width); } } ================================================ FILE: portiaui/app/styles/components/start-url-options.scss ================================================ .start-url-list { overflow-y: auto; min-height: 200px; margin-bottom: 5px; } .start-url-list-title { margin-bottom: 0; } .start-url-generation-list { p { white-space: nowrap; user-select: text; position: relative; margin: 0; } } .fragments-title { line-height: 30px; margin-bottom: 10px; display: inline-block; color: $navbar-default-color; } #add-fragment-button { position: absolute; top: 0; right: 0; line-height: 30px; } ================================================ FILE: portiaui/app/styles/components/tool-group.scss ================================================ .tool-group { display: flex; flex-direction: column; flex-wrap: nowrap; justify-content: flex-start; align-items: stretch; flex: 0 1 auto; overflow: auto; width: 100%; margin-top: $grid-gutter-width; min-height: 0; background-color: $navbar-default-bg; border: 1px solid $navbar-default-border; border-radius: $panel-border-radius; &:last-child { flex: 0.0001 0 auto; margin-bottom: $grid-gutter-width; max-height: none !important; } &.collapsed { flex-grow: 0 !important; flex-shrink: 0 !important; min-height: 0 !important; overflow: hidden; } .tool-group-close { padding: 0 10px; } } .tool-group-header { background-color: $panel-bg; > .nav-tabs { i { padding: 10px 3px; } border-color: $navbar-default-border; > li { > a { margin-top: -1px; &:hover { border-color: $navbar-default-border; } } &.active { > a { background-color: $navbar-default-bg; border-color: $navbar-default-border $navbar-default-border transparent $navbar-default-border; } } &:not(.active) { > a { cursor: pointer !important; } } &:first-of-type { > a { margin-left: -1px; } } } > .tool-group-icons { > a { display: inline-block; margin-right: 0; margin-left: 2px; &, &:hover, &:focus { color: $nav-tabs-active-link-hover-color; border-color: $navbar-default-border transparent; } } } } .collapsed & { > .nav-tabs { > li { > a { cursor: pointer !important; } } } } } .tool-group-collapse { .caret { margin: 0 1px; transition: transform $animation-time $animation-easing; } } .tool-group-content { flex: 1 1 100%; overflow: auto; //transition: opacity $animation-time $animation-easing $animation-time / 3, flex-basis $animation-time / 3 $animation-easing; display: block; min-height: $panel-min-height; opacity: 1; } .tool-group { &.collapsed { .nav-tabs { border-bottom-width: 0; li { margin-bottom: 0; a { margin-bottom: -1px; border-radius: $border-radius-base; } &.active > a { border-color: $navbar-default-border; } } } .tool-group-collapse { .caret { transform: rotate(90deg); } } .tool-group-content { //transition: opacity $animation-time $animation-easing, flex-basis $animation-time / 3 $animation-easing $animation-time; animation: fadeOut $animation-time $animation-easing; display: none; opacity: 0; //flex-basis: 0%; //animation: hideDelay $animation-time $animation-easing forwards; //animation-direction: normal; } } } #actions-group, #inspector-group { flex-shrink: 0; } #extracted-items-group { flex-shrink: 10000; .nav-tabs { .badge { vertical-align: baseline; } } } #options-panels { .tool-group { flex-shrink: 10000; } } ================================================ FILE: portiaui/app/styles/components/tool-panel.scss ================================================ .tool-panel { padding-top: $panel-padding-y; padding-bottom: $panel-padding-y; > div { position: relative; } h3 { display: inline-block; margin-top: 0; color: $navbar-default-color; font-size: $font-size-base; line-height: $tree-list-row-height; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-transform: uppercase; } form { margin-bottom: $line-height-computed; label { font-weight: normal; } } } ================================================ FILE: portiaui/app/styles/components/tooltip-container.scss ================================================ .tooltip-content { @extend .tooltip-inner; > p { margin: ($line-height-computed / 2) 0 0; text-align: left; &.first { margin-top: 0; } } em { font-style: normal; text-decoration: underline; } .tooltip-wide > & { max-width: $tooltip-max-width * 1.5; } } .tooltip-for { pointer-events: auto; } ================================================ FILE: portiaui/app/styles/components/top-bar.scss ================================================ #top-bar { margin-bottom: 0; z-index: 998; &:before, &:after { display: none; } } ================================================ FILE: portiaui/app/styles/components/tree-list.scss ================================================ .tree-list { display: block; margin-bottom: 0; z-index: 0; > .animation-content { padding-left: 0; width: 100%; left: auto; right: 0; & & { width: calc(100% - #{$tree-list-icon-width / 2}); } } } .tree-list-item { display: block; > .animation-content { width: 100%; } } .tree-list-item-row { display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; height: $tree-list-row-height; } .tree-list-item-content { position: relative; flex: 1 1 auto; min-width: 0; color: $navbar-default-color; > a:first-child { flex: 1 1 auto; display: flex; align-items: center; outline: none; overflow: hidden; &:hover, &:focus { text-decoration: none; } &:before { content: ''; display: block; position: absolute; top: 0; bottom: 0; left: 0; right: 0; z-index: -1; background-color: $navbar-default-link-active-bg; border-radius: 4px; opacity: 0; transition: opacity $animation-time $animation-easing; } &.active, &:hover { &:before { opacity: 1; } } } } .tree-list-item-content { &, & > a:only-child { display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; min-width: 0; } } ================================================ FILE: portiaui/app/styles/components/url-bar.scss ================================================ #url-bar { display: flex; flex-direction: row; flex-wrap: nowrap; input { flex: 1 1 auto; z-index: 1; &:focus { z-index: 3; } } .btn { line-height: $line-height-computed; &:focus { outline: none; } } .btn-mode { z-index: 2; transition: background-color $animation-time $animation-easing, border-color $animation-time $animation-easing; cursor: default; @include box-shadow(none); > i { width: 1em; } } .btn-mode-navigation { color: $btn-primary-color; background-color: $btn-primary-bg; border-color: $btn-primary-border; } .btn-mode-data-annotation { color: $btn-success-color; background-color: $btn-success-bg; border-color: $btn-success-border; } } ================================================ FILE: portiaui/app/styles/document.scss ================================================ body { user-select: none; } ================================================ FILE: portiaui/app/styles/droplet.scss ================================================ .droplet { width: 30px; height: 30px; margin: 100px auto; position: absolute; top: -100px; right: 0; z-index: -1; background-color: #333; border-radius: 100%; -webkit-animation: sk-scaleout 2s infinite ease-in-out; animation: sk-scaleout 2s infinite ease-in-out; } @-webkit-keyframes sk-scaleout { 0% { -webkit-transform: scale(0) } 100% { -webkit-transform: scale(1.0); opacity: 0; } } @keyframes sk-scaleout { 0% { -webkit-transform: scale(0); transform: scale(0); } 100% { -webkit-transform: scale(1.0); transform: scale(1.0); opacity: 0; } } ================================================ FILE: portiaui/app/styles/generic.scss ================================================ .txt-describe { color: $light-gray; } .spaced { margin: 20px 0 20px 0; } .has-error { border-color: #a94442; } .mid-align { text-align: center; } .one-half-x { font-size: 1.5em; } .twice-x { font-size: 2em; } .full-width { width: 100%; } .very-opaque { opacity: 0.3; } .flex-center { justify-content: center; } .with-cursor { cursor: pointer; } ================================================ FILE: portiaui/app/styles/layout/_clickable.scss ================================================ .clickable, [data-ember-action] { cursor: pointer; } .ignore-active { &.active { pointer-events: none; } } ================================================ FILE: portiaui/app/styles/layout/_forms.scss ================================================ .input-list-item { $tree-list-caret-padding-y: ($tree-list-row-height - $line-height-computed) / 2; height: $tree-list-row-height - 4px; padding: ($padding-base-vertical - $tree-list-caret-padding-y) $padding-xs-horizontal; } ================================================ FILE: portiaui/app/styles/layout/_full-page-content.scss ================================================ .full-page-content { display: flex; flex-direction: column; flex-wrap: nowrap; justify-content: center; align-items: center; align-content: center; img[alt="Portia logo"] { display: block; flex: 0 0 auto; width: 25%; margin: 0 auto; } > h3 { margin: 2em auto 0; } > p { margin: 1em auto 0; } &:before, &:after { content: ''; display: block; } &:before { flex: 1 1 auto; } &:after { flex: 2 1 auto; } } ================================================ FILE: portiaui/app/styles/templates/application.scss ================================================ #window { height: 100vh; display: flex; flex-direction: column; flex-wrap: nowrap; > section { position: relative; flex: 1 1 auto; display: flex; flex-direction: row; flex-wrap: nowrap; overflow-x: hidden; overflow-y: auto; } } main { order: 0; flex: 1 1 auto; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: stretch; } ================================================ FILE: portiaui/app/styles/templates/browsers.scss ================================================ .browser-list-container { @extend .full-page-content; margin: 0 auto; margin-top: 20px; padding: 0 40px; text-align: center; h3 { margin-top: 0; } } .browser-p { font-size: 1.3em; color: #777; } .browser-mg { margin: none; margin-left: 20px; margin-right: 20px; } .browser-logos { display: flex; margin-top: 26px; max-height: 120px; } .browser-logo { width: 120px; height: 120px; transition: 0.2s; &:hover { transform: translateY(-8px); } } .no-decoration { &:focus, &:hover { text-decoration: none; } } ================================================ FILE: portiaui/app/styles/templates/projects.scss ================================================ $project-list-max-width: 300px; .project-list-container { @extend .full-page-content; width: calc(100% - #{$sidebar-width * 2}); margin: 0 auto; text-align: center; > * { width: 100%; } } .project-list { $project-list-max-width: 300px; $project-list-max-height: 200px; margin: 3em auto 0; max-width: $project-list-max-width; min-height: 0; input { border-radius: 0; border-color: $list-group-border; } .input-group { > .form-control { width: $project-list-max-width; } } .list-group-item { border: none; overflow: hidden; text-overflow: ellipsis; } .project-list-items { width: $project-list-max-width; max-height: $project-list-max-height; overflow: scroll; border: 1px solid $list-group-border; border-top: none; } &.project-within-dropdown { $project-list-max-width: 180px; $project-list-max-height: 100px; margin: 5px auto; max-width: $project-list-max-width; .input-group > .form-control { width: $project-list-max-width; } .project-list-items { width: $project-list-max-width; max-height: $project-list-max-height; } .list-group-item { cursor: pointer; &:hover { color: #555; background-color: #f5f5f5; } } } } .project-create-input { width: $project-list-max-width; } .project-list.not-searchable { .list-group-item { border: 1px solid $list-group-border; } .project-list-items { border: none; } } ================================================ FILE: portiaui/app/templates/application.hbs ================================================
{{loading-slider isLoading=loading duration=200}}
{{notification-container}} {{outlet 'side-bar'}} {{#sliding-main}} {{outlet 'options-panels'}} {{outlet 'main'}} {{outlet 'tool-panels'}} {{/sliding-main}}
================================================ FILE: portiaui/app/templates/branding.hbs ================================================ Portia beta ================================================ FILE: portiaui/app/templates/browsers.hbs ================================================

Unfortunately your browser doesn't support some of the features required to give you a great experience with Portia.

Please try using an up-to-date version of one of these browsers, which are known to work well with Portia.

{{browser-list browsers=model}}
================================================ FILE: portiaui/app/templates/components/.gitkeep ================================================ ================================================ FILE: portiaui/app/templates/components/add-start-url-button.hbs ================================================ {{#tooltip-container tooltipFor="start-url-button" tooltipContainer='body' as |options|}} {{#if (eq options.section 'tooltip')}} Toggle start page {{#if newStartUrl}}

Add this page as a start page for your spider

{{else}}

Remove this page from your spider's start pages

{{/if}} {{else}} {{/if}} {{/tooltip-container}} ================================================ FILE: portiaui/app/templates/components/animation-container.hbs ================================================
{{yield}}
================================================ FILE: portiaui/app/templates/components/annotation-options.hbs ================================================

Annotation

{{#help-icon}} Only extract items that have this annotation. Only this sample will be affected {{/help-icon}}
{{select-box name="selectionMode" value=(mut selectionMode) valueAttribute='label' choices=selectionModeOptions onChange=(action "save")}}
{{#if (not-eq annotation.selectionMode 'auto')}}
{{#if (eq annotation.selectionMode 'css')}} {{buffered-input type="text" name="selector" class="form-control" value=(mut cssSelector) viewValue=(mut editedCssSelector) onChange=(action 'save')}} The input value is not a valid CSS selector. {{else}} {{input type="text" name="selector" class="form-control" value=(get annotation annotation.selectionMode) readonly=true}} {{/if}}
{{/if}}
{{select-box name="attribute" value=(mut attribute) valueAttribute='name' choices=attributes onChange=(action "save")}}
================================================ FILE: portiaui/app/templates/components/browser-iframe.hbs ================================================ ================================================ FILE: portiaui/app/templates/components/browser-list.hbs ================================================
{{#each browsers as |browser|}}

{{browser.name}}

{{/each}}
================================================ FILE: portiaui/app/templates/components/browser-url-blocked.hbs ================================================ Portia is having trouble loading this page at the moment. Try a different page or try again later. ================================================ FILE: portiaui/app/templates/components/browser-url-failing.hbs ================================================ Portia is currently having trouble loading this page would you like to try again? ================================================ FILE: portiaui/app/templates/components/browser-view-port.hbs ================================================
{{url-bar class="navbar-form" role="navigation"}}
{{yield (hash section="toolbar")}}
{{#if webSocket.connecting}} Connecting ... {{else if webSocket.closed}} {{#if webSocket.secondsUntilReconnect }} Reconnecting to Portia server in {{webSocket.secondsUntilReconnect}} seconds. {{else if websocket.reconnectMessage}} {{websocket.reconnectMessage}} {{/if}} {{#unless webSocket.reconnectImminent}} Try Again. {{/unless}} {{else if webSocket.reconnectComponent}} {{component webSocket.reconnectComponent}} {{/if}}
{{yield (hash section="overlays")}}
{{browser-iframe clickHandler=(action 'viewPortClick')}}
Portia logo

What would you like to scrape?

{{url-bar class="navbar-form" role="navigation" autofocus=true}} {{#if uiState.models.project.spiders.length}}

You can also select one of your existing spiders from the sidebar.

{{/if}}
================================================ FILE: portiaui/app/templates/components/buffered-input.hbs ================================================ {{input id=inputId type=type class=(concat "form-control " (if focused "focused ") class) value=(mut displayedValue) enter=(if focused (action 'endEditing' 'enter')) escape-press=(if focused (action 'cancelEditing')) focus-in=(action 'startEditing') bubbles=true focus-out=(if focused (action 'endEditing' 'focus-out')) placeholder=placeholder autofocus=autofocus disabled=disabled spellcheck=spellcheck}} ================================================ FILE: portiaui/app/templates/components/colored-badge.hbs ================================================ {{#if hasBlock}}{{yield}}{{else}}{{value}}{{/if}} ================================================ FILE: portiaui/app/templates/components/colored-span.hbs ================================================ {{~ yield ~}} ================================================ FILE: portiaui/app/templates/components/combo-box.hbs ================================================ {{#dropdown-widget class="combo-box" events=this open=(mut open) active=(mut viewValue) focused=value orderItemsForSearch=orderItemsForSearch valuesEqual=valuesEqual menuContainer=menuContainer menuClass=menuClass menuAlign=menuAlign onClose=(action 'menuClosed') as |widget|}} {{#if (eq widget.section 'widget')}}
{{input id=inputId type="text" class=(concat "form-control dropdown-toggle " inputClass) value=query escape-press=(action widget.closeMenu 'escape') focus-in=(chain-actions widget.openMenu widget.focusIn) bubbles=true focus-out=(chain-actions widget.focusOut (action 'restoreFocus')) spellcheck=spellcheck}}
{{currentValue}} {{else if (eq widget.section 'menu')}} {{#if hasBlock}} {{yield (hash menu=widget.menu header=widget.header item=widget.item divider=widget.divider query=query setValue=(action 'setValue') setViewValue=(action 'setViewValue') setValueAndClose=(action 'setValueAndClose') closeMenu=widget.closeMenu)}} {{else}} {{#each choices as |choice|}} {{#widget.item value=choice action=(action 'setValueAndClose' choice)}} {{#if valueAttribute}} {{get choice valueAttribute}} {{else}} {{choice}} {{/if}} {{/widget.item}} {{/each}} {{/if}} {{/if}} {{/dropdown-widget}} ================================================ FILE: portiaui/app/templates/components/create-project-button.hbs ================================================ {{#if canCreateProjects}}

{{input type="text" class="form-control" value=(mut projectName) placeholder="Create a new project" enter=(action 'addProject')}}
{{#if projects}}
OR
{{/if}} {{/if}} ================================================ FILE: portiaui/app/templates/components/create-spider-button.hbs ================================================ ================================================ FILE: portiaui/app/templates/components/data-structure-annotations.hbs ================================================ {{#tree-list-item hasChildren=item.annotations.length onMouseEnter=(action 'enterItem' item) onMouseLeave=(action 'leaveItem' item) as |options|}} {{#if (eq options.section "item")}} {{yield}} {{else if (eq options.section "subtrees")}} {{#each item.annotations as |annotation|}} {{#if (eq annotation.constructor.modelName "annotation")}} {{#tree-list-item onMouseEnter=(action 'enterAnnotation' annotation) onMouseLeave=(action 'leaveAnnotation' item) as |options|}} {{#link-to 'projects.project.spider.sample.data.annotation' annotation}} {{indentation-spacer isSmall=true}} {{list-item-badge value=(or annotation.elements.length 0) color=(array-get annotationColors annotation.orderedIndex) }} {{list-item-icon icon=annotation.type}} {{list-item-annotation-field annotation=annotation selecting=(mut annotation.new)}} {{#list-item-field-type field=annotation.field}} Change type of selected field {{/list-item-field-type}} {{#link-to 'projects.project.spider.sample.data.annotation.options' annotation bubbles=false class="ignore-active"}} {{list-item-icon icon='options'}} {{/link-to}} {{list-item-icon icon='remove' action=(action 'removeAnnotation' annotation) bubbles=false}} {{/link-to}} {{/tree-list-item}} {{else if (eq annotation.constructor.modelName "item")}} {{#data-structure-annotations sample=sample item=annotation annotationColors=annotationColors}} {{#link-to 'projects.project.spider.sample.data.item' annotation}} {{list-item-icon icon='schema'}} {{list-item-badge value=(or annotation.elements.length 0)}} {{list-item-editable value=(mut annotation.name) editing=(mut annotation.new) onChange=(action 'saveItem' annotation)}} {{list-item-item-schema item=annotation}} {{list-item-add-annotation-menu item=annotation}} {{list-item-icon icon='remove' action=(action 'removeItem' annotation) bubbles=false}} {{/link-to}} {{/data-structure-annotations}} {{/if}} {{/each}} {{/if}} {{/tree-list-item}} ================================================ FILE: portiaui/app/templates/components/data-structure-listing.hbs ================================================ {{#tree-list}} {{#tree-list-item hasChildren=sample.items.length as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title"}} Items {{/list-item-text}} {{list-item-icon icon='add' action=(action 'addItem' sample)}} {{else if (eq options.section "subtrees")}} {{#each sample.items as |item|}} {{#unless item.parent}} {{#data-structure-annotations sample=sample item=item annotationColors=annotationColors}} {{#link-to 'projects.project.spider.sample.data.item' item}} {{list-item-badge value=(or item.elements.length 0)}} {{list-item-icon icon='schema'}} {{list-item-item-schema item=item selecting=(mut item.new)}} {{list-item-add-annotation-menu item=item}} {{list-item-icon icon='remove' action=(action 'removeItem' item) disabled=(lte sample.items.length 1) bubbles=false}} {{/link-to}} {{/data-structure-annotations}} {{/unless}} {{/each}} {{/if}} {{/tree-list-item}} {{/tree-list}} ================================================ FILE: portiaui/app/templates/components/dropdown-delete.hbs ================================================ {{list-item-icon class="icon" icon="remove"}}{{if isConfirmed 'Are you sure?' text}} ================================================ FILE: portiaui/app/templates/components/dropdown-divider.hbs ================================================ ================================================ FILE: portiaui/app/templates/components/dropdown-header.hbs ================================================ {{yield}} ================================================ FILE: portiaui/app/templates/components/dropdown-item.hbs ================================================ {{#if hasBlock}} {{yield value}} {{else}} {{value}} {{/if}} ================================================ FILE: portiaui/app/templates/components/dropdown-menu.hbs ================================================ {{yield (hash menu=this header=(component 'dropdown-header') item=(component 'dropdown-item' menu=this) divider=(component 'dropdown-divider'))}} ================================================ FILE: portiaui/app/templates/components/dropdown-widget.hbs ================================================ {{yield (hash section='widget' openMenu=(action 'openMenu') closeMenu=(action 'closeMenu') toggleMenu=(action 'toggleMenu') focusIn=(action 'focusIn') focusOut=(action 'focusOut') keyDown=(action 'keyDown'))}} {{#dropdown-menu class=menuClasses events=events keyNavigate=keyNavigate active=(mut active) focused=(mut focused) orderItemsForSearch=orderItemsForSearch valuesEqual=valuesEqual onFocusIn=(action 'focusIn') onFocusOut=(action 'focusOut') as |options|}} {{#if open}} {{yield (hash section='menu' menu=options.menu header=options.header item=options.item divider=options.divider openMenu=(action 'openMenu') closeMenu=(action 'closeMenu') toggleMenu=(action 'toggleMenu') focusIn=(action 'focusIn') focusOut=(action 'focusOut') keyDown=(action 'keyDown'))}} {{/if}} {{/dropdown-menu}} ================================================ FILE: portiaui/app/templates/components/edit-sample-button.hbs ================================================ {{#if editableSample}} {{#link-to 'projects.project.spider.sample' editableSample class="btn btn-primary"}} {{icon-button icon='sample'}} Edit sample {{/link-to}} {{else}} {{#tooltip-container tooltipFor="add-spider-browser-button" tooltipContainer='body' as |options|}} {{#if (eq options.section 'tooltip')}} {{#unless editableSample}} Create a new sample from the current page so you can start annotating the data you want to extract {{#unless sameDomain}}

This spider is from a different domain to your spider. Maybe you would like to create a new spider for this sample?

{{/unless}} {{/unless}} {{else}} {{/if}} {{/tooltip-container}} {{/if}} ================================================ FILE: portiaui/app/templates/components/element-overlay.hbs ================================================ {{#each rects key="@index" as |rect index|}} {{element-rect-overlay index=index icon=icon color=color positionMode=positionMode class=class overlay=this}} {{/each}} ================================================ FILE: portiaui/app/templates/components/element-rect-overlay.hbs ================================================
{{icon-button icon=icon}}
================================================ FILE: portiaui/app/templates/components/extracted-item-table.hbs ================================================ {{#each-in item as |key value|}} {{#if (is-array value)}} {{key}} {{#each value key='@index' as |item|}} {{#if (is-object item)}} {{extracted-item-table item=item}} {{else}}
{{item}}
{{/if}} {{/each}} {{else if (is-object value)}} {{key}} {{#unless (is-empty-object value)}} {{extracted-item-table item=value}} {{/unless}} {{else}} {{key}} {{value}} {{/if}} {{/each-in}} ================================================ FILE: portiaui/app/templates/components/extracted-items-group.hbs ================================================ {{#tool-group id="extracted-items-group" as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="extracted-items"}} {{#extracted-items-tab}} Extracted items {{/extracted-items-tab}} {{/group.tab}} {{#group.tab toolId="extracted-items-json"}} JSON {{/group.tab}} {{extracted-items-status}} {{else if (eq group.section "panels")}} {{#group.panel class="extracted-items container-fluid" toolId="extracted-items" as |active|}} {{extracted-items-panel selected=active}} {{/group.panel}} {{#group.panel class="extracted-items-json" toolId="extracted-items-json" as |active|}} {{extracted-items-json-panel selected=active}} {{/group.panel}} {{/if}} {{/tool-group}} ================================================ FILE: portiaui/app/templates/components/extracted-items-json-panel.hbs ================================================ a {{#if selected ~}} {{extracted-items-json json=extractedItems.items position=0}} {{~/if}} ================================================ FILE: portiaui/app/templates/components/extracted-items-json-value.hbs ================================================ {{#if fromArray}}{{depthSpaces}}{{/if}} {{escapedValue}}{{comma}} ================================================ FILE: portiaui/app/templates/components/extracted-items-json.hbs ================================================ {{#if (is-object-or-array json) ~}} {{#if showOpen ~}} {{#unless fromKey}} {{openingCharacter}} {{/unless}} {{~#if openChild ~}} {{depthPlus1Spaces}}{{openChild}} {{~#if (is-object json)}}
{{/if~}} {{/if}} {{~/if}} {{#if (is-array json) ~}} {{#each json as |value index| ~}} {{#if (and fromKey (not index))}}{{/if}} {{extracted-items-json json=value position=index from='array' parent=json depth=depth ~}} {{~/each}} {{else if (is-object json) ~}} {{#if (and fromKey (not index))}}{{/if}} {{#each-in (indexed-object json) as |key v| ~}} {{depthPlus1Spaces}}"{{key}}": {{#if (is-array v.value)}}[{{/if}}{{#if (is-object v.value)}}{ {{/if}} {{~extracted-items-json json=v.value position=v.index from='key' parent=json depth=depth key=key ~}} {{~/each-in}} {{~/if}} {{~#if openSibling ~}} {{depthSpaces}}{{closingCharacter}}{{comma}} {{depthSpaces}}{{openSibling}} {{else}} {{depthSpaces}}{{closingCharacter}}{{comma}} {{~/if ~}} {{else ~}} {{extracted-items-json-value value=json depth=depth position=position maxPosition=maxPosition key=key from=from ~}} {{~/if}} ================================================ FILE: portiaui/app/templates/components/extracted-items-panel.hbs ================================================ {{#if isExtracting}}
Extracting data...
{{/if}} {{#if failedExtraction}}
{{failedMsg}}
{{/if}} {{#if (and selected (not isExtracting))}} {{#each extractedItems.items key='@index' as |item|}} {{extracted-item-table item=item}} {{/each}} {{/if}} ================================================ FILE: portiaui/app/templates/components/extracted-items-status.hbs ================================================ {{#link-to changeInfo.path changeInfo.model bubbles=false}} {{#help-icon icon=icon placement='left'}} {{#if hasWarning}} {{changeInfo.text}} {{else}} Your sample is correctly configured for extraction {{/if}} {{/help-icon}} {{/link-to}} ================================================ FILE: portiaui/app/templates/components/extracted-items-tab.hbs ================================================ {{yield}} {{#unless isExtracting}} {{numItems}} {{/unless}} ================================================ FILE: portiaui/app/templates/components/extractor-options.hbs ================================================ {{#tree-list class="extractor-options"}} {{#tree-list-item hasChildren=true as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title"}} Extractors {{/list-item-text}} {{#list-item-icon-menu icon='add-dropdown' as |dropdown|}} {{#dropdown.header}}Add field type extractor{{/dropdown.header}} {{#each types as |type|}} {{#dropdown.item action=(chain-actions (action 'addTypeExtractor' type) dropdown.closeMenu) as |value|}} {{list-item-icon class="icon" icon=type}}{{type}} {{/dropdown.item}} {{/each}} {{#dropdown.header}}Add regular expression extractor{{/dropdown.header}} {{#each regexExtractors as |extractor|}} {{#dropdown.item action=(chain-actions (action 'addRegexExtractor' extractor) dropdown.closeMenu) as |value|}} {{list-item-icon class="icon" icon="regular expression"}}{{extractor.value}} {{/dropdown.item}} {{/each}} {{#dropdown.item action=(chain-actions (action 'addNewRegexExtractor') dropdown.closeMenu) as |value|}} {{list-item-icon class="icon" icon="add"}}New regular expression {{/dropdown.item}} {{/list-item-icon-menu}} {{else if (eq options.section "subtrees")}} {{#each annotation.extractors as |extractor|}} {{#tree-list-item}} {{#if (eq extractor.type 'type')}} {{list-item-icon icon=extractor.value}} {{#list-item-text}} {{extractor.value}} {{/list-item-text}} {{else if (eq extractor.type 'regex')}} {{list-item-icon icon='regular expression'}} {{list-item-editable value=(mut extractor.value) editing=(mut extractor.new) onChange=(action 'saveExtractor' extractor)}} {{/if}} {{list-item-icon icon='remove' action=(action 'removeExtractor' extractor) bubbles=false}} {{/tree-list-item}} {{/each}} {{/if}} {{/tree-list-item}} {{/tree-list}} ================================================ FILE: portiaui/app/templates/components/feed-url-options.hbs ================================================

Enter a publicly available URL containing newline separated URLs like this.

{{input type="text" id='feedUrl' class="form-control focus-control" value=(mut startUrl.url) focus-out="saveFeedUrl" placeholder='https://gist.github.com/user/gist_id' }}
================================================ FILE: portiaui/app/templates/components/field-options.hbs ================================================

Field

{{#help-icon}} Only extract items that have this field. All samples using this data format will be affected {{/help-icon}}
{{#help-icon}} The value of this field will be ignored when checking for duplicate items {{/help-icon}}
================================================ FILE: portiaui/app/templates/components/fragment-options.hbs ================================================ {{#if changeset.isValid}} {{list-item-badge value=multiplicity color=fragmentColor}} {{else}} {{#tooltip-container toggleTooltip=toggleTooltip tooltipContainer='body' tooltipFor=(concat 'error-icon-' elementId) placement='left' as |tooltip|}} {{#if (eq tooltip.section 'tooltip')}} {{changeset.error.value.validation}} {{else}} {{icon-button id=(concat 'error-icon-' elementId) icon='error-triangle' class='fragment-error tooltip-for'}} {{/if}} {{/tooltip-container}} {{/if}}
{{#if isRange}} {{input type="text" class="form-control compact-control fragment-left-half focus-control" value=(mut lower) placeholder="start" focus-out=(action 'saveFragment')}} - {{input type="text" class="form-control compact-control fragment-right-half" value=(mut higher) placeholder="end" focus-out=(action 'saveFragment')}} {{else}} {{input type="text" class="form-control compact-control fragment-input focus-control" value=(mut changeset.value) placeholder=listPlaceholder focus-out=(action 'saveFragment') key-up=(action 'updateValue')}} {{/if}}
{{select-box buttonClass="compact-control fragment-type" value=(mut fragmentType) valueAttribute='label' choices=fragmentTypes isDisabled=(eq index 0) onClick=(action 'changeFragmentType') }}
{{#if (not-eq index 0)}} {{list-item-icon class='fragment-action-icon' icon='remove' action=(action removeFragment fragment) bubbles=false }} {{/if}} ================================================ FILE: portiaui/app/templates/components/generated-url-options.hbs ================================================ {{#list-item-text class="title fragments-title"}} Fragments {{#help-icon}} Fragments

A generated url is made up of one or more fragments. A fragment can be a single value, a list of different values or a range of numbers.

Using fragments you can create a large number of urls.

{{/help-icon}} {{/list-item-text}} {{#tooltip-container tooltipFor="add-fragment-button" text="Create a new fragment to generate URLs" tooltipContainer='body'}} {{list-item-icon icon='add' id="add-fragment-button" action=(action 'addFragment') disabled=(not allValidFragments)}} {{/tooltip-container}} {{#each fragments as |fragment index|}} {{fragment-options index = index fragment = fragment saveSpider = saveSpider fragmentColor = (array-get fragmentColors index) removeFragment = (action 'removeFragment') allValidFragments = allValidFragments }} {{/each}}

Generation List

{{#each generatedUrlLists as |generatedUrlList|}}

{{#each generatedUrlList as |fragment index| ~}} {{#colored-span color=(array-get fragmentColors index) ~}} {{fragment}} {{~/colored-span}} {{~/each}}

{{/each}} {{#if (not isComplete)}} {{tooltip-icon icon='vertical-ellipsis' text='This list only shows the first few generated urls.' modifyClasses='one-half-x full-width' }} {{/if}}
================================================ FILE: portiaui/app/templates/components/help-icon.hbs ================================================ {{#tooltip-container tooltipClasses=tooltipClasses tooltipFor=(concat "help-icon-" elementId) tooltipContainer=tooltipContainer placement=placement as |tooltip|}} {{#if (eq tooltip.section 'tooltip')}} {{yield}} {{else}} {{icon-button id=(concat "help-icon-" elementId) class=classes icon=icon}} {{/if}} {{/tooltip-container}} ================================================ FILE: portiaui/app/templates/components/icon-button.hbs ================================================ ================================================ FILE: portiaui/app/templates/components/input-with-clear.hbs ================================================ {{input class="form-control" value=(mut value) placeholder=placeholder keyUp=(action "keyUp" on="key-up")}} {{icon-button class="clear-input" icon='close' action=(action 'clear')}} ================================================ FILE: portiaui/app/templates/components/inspector-panel.hbs ================================================ {{#if inspectedElement}}
{{elementPath}}
{{#each attributes as |attribute|}} {{/each}}
{{attribute.name}}
{{attribute.value}}
{{#with (attribute-annotation (get sample.dataStructure.annotations (guid inspectedElement)) attribute.name) as |annotation|}}
{{#if annotation.name}} {{colored-badge value=annotation.name color=(array-get annotationColors annotation.orderedIndex)}} {{/if}} {{icon-button icon='add' action=(action 'addAnnotation' attribute.attribute) bubbles=false}}
{{/with}}
{{else}}

No element selected

{{/if}} ================================================ FILE: portiaui/app/templates/components/json-file-compare.hbs ================================================ {{#if isArray}} [{{#each entries as |entry index|}} {{#if entry.conflict}} {{#each entries as |entry|}} {{json-file-compare json=entry.json path=entry.path update="update" multi=true}} {{/each}} {{else}} {{entry.value}}, {{/if}} {{/each}}] {{else if isObject}} {{#if isConflict}} {{#if isResolved}} RESOLVED
[CHANGE SELECTION] {{resolvedRepr}},
{{else}} CONFLICT
{{#each conflictValues as |value|}}
{{value.label}}: {{#unless value.accepted}} {{/unless}} {{#if multi}} {{#unless value.rejected}} {{/unless}} {{/if}} {{value.value}}
{{/each}}
{{/if}} {{else}}
{{#each entries as |entry|}}
{{entry.key}}:{{json-file-compare json=entry.json path=entry.path update="update"}}
{{/each}}
{{/if}} {{else}} {{value}} {{/if}} ================================================ FILE: portiaui/app/templates/components/link-crawling-options.hbs ================================================

Crawling rules

{{#if (eq spider.linksToFollow 'all')}}
Following all encountered links within the same domains
{{else if (eq spider.linksToFollow 'none')}}
Not following any links
{{else if (eq spider.linksToFollow 'patterns')}}
Follow links that match these patterns
{{regex-pattern-list list=spider.followPatterns onChange=(action 'save')}}
Exclude links that match these patterns
{{regex-pattern-list list=spider.excludePatterns onChange=(action 'save')}} {{/if}}
================================================ FILE: portiaui/app/templates/components/list-item-add-annotation-menu.hbs ================================================ {{#list-item-icon-menu icon='add-dropdown' as |options|}} {{#options.item value="Add annotation" action=(chain-actions (action 'addAnnotation') options.closeMenu) as |value|}} {{list-item-icon class="icon" icon="add"}}{{value}} {{/options.item}} {{#if allowNesting}} {{#options.item value="Add nested item" action=(chain-actions (action 'addNestedItem') options.closeMenu) as |value|}} {{list-item-icon class="icon" icon="add"}}{{value}} {{/options.item}} {{/if}} {{/list-item-icon-menu}} ================================================ FILE: portiaui/app/templates/components/list-item-annotation-field.hbs ================================================ {{#list-item-relation-manager value=(mut annotation.field) choices=annotation.parent.schema.fields selecting=(mut selecting) onChange=(action 'changeField') validate=(action 'validateFieldName') create=(action 'addField') as |options|}} {{#if (eq options.section 'change-header')}} Type to change the field {{else if (eq options.section 'choices-header')}} Select an existing field {{else if (eq options.section 'choice')}} {{list-item-icon class="icon" icon=options.choice.type}}{{options.choice.name}} {{/if}} {{/list-item-relation-manager}} ================================================ FILE: portiaui/app/templates/components/list-item-badge.hbs ================================================ {{#if hasBlock}}{{yield}}{{else}}{{value}}{{/if}} ================================================ FILE: portiaui/app/templates/components/list-item-combo.hbs ================================================ {{#if selecting}} {{#if hasBlock}} {{#combo-box choices=choices value=(mut value) valueAttribute=valueAttribute open=(mut selecting) orderItemsForSearch=orderItemsForSearch valuesEqual=valuesEqual onChange=onChange autoSelect=autoSelect inputClass=(concat "input-list-item " inputClass) menuClass=menuClass menuAlign=menuAlign menuContainer=menuContainer as |options|}} {{yield options}} {{/combo-box}} {{else}} {{combo-box choices=choices value=(mut value) valueAttribute=valueAttribute open=(mut selecting) orderItemsForSearch=orderItemsForSearch valuesEqual=valuesEqual onChange=onChange autoSelect=autoSelect inputClass=(concat "input-list-item " inputClass) menuClass=menuClass menuAlign=menuAlign menuContainer=menuContainer}} {{/if}} {{else}} {{#if valueAttribute}} {{get value valueAttribute}} {{else}} {{value}} {{/if}} {{/if}} ================================================ FILE: portiaui/app/templates/components/list-item-editable.hbs ================================================ {{#if editing}} {{buffered-input class="input-list-item" value=(mut value) focused=editing autoSelect=true spellcheck=spellcheck onChange=onChange validate=validate autofocus="autofocus"}} {{else}} {{value}} {{icon-button icon='edit' action=(action 'startEditing') bubbles=false}} {{/if}} ================================================ FILE: portiaui/app/templates/components/list-item-field-type.hbs ================================================ {{#list-item-selectable value=(mut field.type) onChange=(action 'saveField') menuContainer="body" menuAlign="right" as |select|}} {{#if hasBlock}} {{#select.header}} {{yield}} {{/select.header}} {{/if}} {{#each types as |type|}} {{#select.item value=type action=(action select.setValueAndClose type)}} {{list-item-icon class="icon" icon=type}}{{type}} {{/select.item}} {{/each}} {{/list-item-selectable}} ================================================ FILE: portiaui/app/templates/components/list-item-icon-menu.hbs ================================================ {{#dropdown-widget class="list-item-icon" menuContainer="body" menuAlign="right" as |options|}} {{#if (eq options.section 'widget')}} {{list-item-icon onClick=(action 'clickIcon') icon=icon action=options.toggleMenu tabindex=-1}} {{else if (eq options.section 'menu')}} {{yield options}} {{/if}} {{/dropdown-widget}} ================================================ FILE: portiaui/app/templates/components/list-item-icon.hbs ================================================ ================================================ FILE: portiaui/app/templates/components/list-item-item-schema.hbs ================================================ {{#list-item-relation-manager value=(mut item.schema) choices=item.ownerSample.spider.project.schemas selecting=(mut selecting) onChange=(action 'changeSchema') create=(action 'addSchema') as |options|}} {{#if (eq options.section 'change-header')}} Type to change the data format {{else if (eq options.section 'choices-header')}} Select an existing data format {{else if (eq options.section 'choice')}} {{list-item-icon class="icon" icon='schema'}}{{options.choice.name}} {{/if}} {{/list-item-relation-manager}} ================================================ FILE: portiaui/app/templates/components/list-item-link-crawling.hbs ================================================ {{#list-item-selectable value=(mut linksToFollow) valueAttribute='label' onChange=(action 'saveSpider') menuContainer="body" menuAlign="left" as |select|}} {{#select.header}} Change how links are crawled {{/select.header}} {{#each followPatternOptions as |option|}} {{#select.item value=option action=(action select.setValueAndClose option)}} {{option.label}} {{/select.item}} {{/each}} {{/list-item-selectable}} {{#help-icon}} {{linksToFollow.description}} {{/help-icon}} ================================================ FILE: portiaui/app/templates/components/list-item-relation-manager.hbs ================================================ {{#list-item-combo value=(mut value.content) valueAttribute='name' selecting=(mut selecting) orderItemsForSearch=orderItemsForSearch valuesEqual=valuesEqual onChange=onChange autoSelect=true menuContainer="body" as |combo|}} {{#combo.header}} {{yield (hash section='change-header')}} {{/combo.header}} {{#combo.item value=(hash special="rename" name=combo.query onMenuClosed=(action 'rename' combo.query)) disabled=(not combo.menu.active.special) action=(chain-actions (action 'rename' combo.query) (action combo.closeMenu 'escape'))}} {{list-item-icon class="icon" icon="edit"}}Rename to “{{combo.query}}” {{/combo.item}} {{#combo.item value=(hash special="add" name=combo.query onMenuClosed=(action 'add' combo.query)) disabled=(not combo.menu.active.special) action=(chain-actions (action 'add' combo.query) (action combo.closeMenu 'escape'))}} {{list-item-icon class="icon" icon="add"}}Add “{{combo.query}}” {{/combo.item}} {{combo.divider}} {{#combo.header}} {{yield (hash section='choices-header')}} {{/combo.header}} {{#each sortedChoices as |choice|}} {{#combo.item value=choice action=(action combo.setValueAndClose choice)}} {{yield (hash section='choice' choice=choice)}} {{/combo.item}} {{/each}} {{/list-item-combo}} ================================================ FILE: portiaui/app/templates/components/list-item-selectable.hbs ================================================ {{#if selecting}} {{#if hasBlock}} {{#select-box choices=choices value=(mut value) valueAttribute=valueAttribute open=(mut selecting) onChange=onChange buttonClass=(concat "input-list-item " buttonClass) menuClass=menuClass menuAlign=menuAlign menuContainer=menuContainer as |options|}} {{yield options}} {{/select-box}} {{else}} {{select-box choices=choices value=(mut value) valueAttribute=valueAttribute open=(mut selecting) onChange=onChange buttonClass=(concat "input-list-item " buttonClass) menuClass=menuClass menuAlign=menuAlign menuContainer=menuContainer}} {{/if}} {{else}} {{#if valueAttribute}} {{get value valueAttribute}} {{else}} {{value}} {{/if}} {{/if}} ================================================ FILE: portiaui/app/templates/components/list-item-text.hbs ================================================ {{yield}} ================================================ FILE: portiaui/app/templates/components/notification-container.hbs ================================================ {{#each banners as |notification|}} {{notification-message notification=notification fade=notification.fading fadeAction=(action 'fadeBanner' notification)}} {{/each}} {{#each displayNotifications as |notification|}} {{notification-message notification=notification fade=notification.fading closeAction=(action 'dismissNotification' notification) fadeAction=(action 'fadeNotification' notification)}} {{/each}} ================================================ FILE: portiaui/app/templates/components/notification-message.hbs ================================================ {{#if closeAction}} {{/if}} {{#if title}}

{{title}}

{{/if}}

{{message}}

================================================ FILE: portiaui/app/templates/components/page-actions-editor.hbs ================================================ {{#if editing }} {{#if addingNew}}
{{else}}
{{#if (eq editing.type "wait")}}
{{input value=editing.timeout pattern="^[0-9]+$" class="form-control" }}
{{else}}
{{input value=editing.selector class="form-control" }}
{{/if}} {{#if (eq editing.type "set")}}
{{input value=editing.value class="form-control" }}
{{/if}}
{{input value=editing.accept class="form-control" }}
{{input value=editing.reject class="form-control" }}
{{/if}} {{else}} {{#tree-list}} {{#tree-list-item hasChildren=true childsReorderable=true reorder=(action "reorderPageAction") as |options|}} {{#if (eq options.section "item")}} {{#list-item-text}} OnLoad {{/list-item-text}} {{list-item-icon icon='add' action=(action "addNew") }} {{else if (eq options.section "subtrees")}} {{#each pageActions as |action index|}} {{#tree-list-item classNames="page-action" as |options|}} {{reorder-handler}} {{list-item-icon icon=action.type}} {{#list-item-text}} {{#if action.selector}}{{action.selector}}{{/if}} {{#if action.value}} to "{{action.value}}"{{/if}} {{#if action.timeout}} for {{action.timeout}}ms{{/if}} {{/list-item-text}} {{list-item-icon icon='options' action=(action "editPageAction" action)}} {{list-item-icon icon='remove' action=(action "deletePageAction" index)}} {{/tree-list-item}} {{else}} {{#tree-list-item}} {{#list-item-text}} No actions have been recorded yet{{/list-item-text}} {{/tree-list-item}} {{/each}} {{/if}} {{/tree-list-item}} {{/tree-list}} {{/if}} ================================================ FILE: portiaui/app/templates/components/project-list.hbs ================================================ {{#if showSearch}} {{input-with-clear update=(action "search") clear=(action "clear") placeholder="Search..."}}
{{#each filteredProjects as |project|}} {{#if isSelecting}}
{{project.name}}
{{else}} {{link-to project.name 'projects.project' project.id class="list-group-item" }} {{/if}} {{/each}}
{{else}}
{{#each projects as |project|}} {{#if isSelecting}}
{{project.name}}
{{else}} {{link-to project.name 'projects.project' project.id class="list-group-item" }} {{/if}} {{/each}}
{{/if}} ================================================ FILE: portiaui/app/templates/components/project-listing.hbs ================================================ {{#tree-list}} {{#tree-list-item hasChildren=true as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title project-listing"}} Project {{#animation-container hide=isPublished class="inline project-changes" setHeight=false }} {{#link-to 'projects'}}Show all projects{{/link-to}} {{/animation-container}} {{#animation-container hide=notPublished id="project-changes-info" class="inline project-changes" setHeight=false}} Not published {{#help-icon tooltipClasses="tooltip-wide"}} Not published

This project has changes that have not yet been published.

When you make changes in Portia a private workspace is created for your user, separate from the rest of the project. Other users cannot see these changes until they are published, and you cannot see changes that were published by other users after you started making changes.

To run a spider or make your changes visible to other users you must first publish ({{icon-button icon='publish'}}) the changes.

To clean your private workspace, and get back to the most recently published version of your project, you can discard your changes ({{icon-button icon='rollback'}}).

{{/help-icon}} {{/animation-container}} {{/list-item-text}} {{else if (eq options.section "subtrees")}} {{#tree-list-item}} {{#link-to 'projects.project' project}} {{indentation-spacer}} {{list-item-icon icon='project'}} {{#list-item-text}} {{project.name}} {{/list-item-text}} {{/link-to}} {{#list-item-icon-menu onClick=(action 'clickProjectOptions') icon='vertical-ellipsis' as |options| }} {{#if (and versionControlled hasChanges)}}
  • {{list-item-icon class="icon" icon="publish"}}Publish project
  • {{list-item-icon class="icon" icon="rollback"}}Discard changes
  • {{else if deployable}}
  • {{list-item-icon class="icon" icon="publish"}}Deploy project
  • {{/if}}
  • {{list-item-icon class="icon" icon="download"}}Download as Portia
  • {{list-item-icon class="icon" icon="code"}}Download as Scrapy
  • {{/list-item-icon-menu}}
    {{/tree-list-item}} {{/if}} {{/tree-list-item}} {{/tree-list}} ================================================ FILE: portiaui/app/templates/components/project-structure-listing.hbs ================================================ {{#tree-list hide=currentSchema}} {{#tree-list-item hasChildren=true as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title"}} Spider{{#animation-container class="inline" hide=currentSpider setHeight=false}}s {{/animation-container}} {{pagination}} {{#animation-container class="inline" setHeight=false}} {{#help-icon}} Spiders

    A spider crawls web pages to extract data.

    It is most common to create a spider for each website you wish to crawl, but a single spider can also crawl more than one website.

    To create a spider first visit a web page that you would like to start crawling from.

    {{/help-icon}} {{/animation-container}} {{spider-message currentSpider=currentSpider}} {{/list-item-text}} {{#if currentSpider}} {{#animation-container}} {{#link-to 'projects.project' project class='inline project-change'}} Show all spiders {{/link-to}} {{/animation-container}} {{else}} {{#tooltip-container tooltipFor="add-spider-button" text=addSpiderTooltipText tooltipContainer='body'}} {{list-item-icon id="add-spider-button" icon='add' disabled=(not canAddSpider) action=(action 'addSpider')}} {{/tooltip-container}} {{/if}} {{else if (eq options.section "subtrees")}} {{#tree-list-item hide=(or project.spiders.isPending project.spiders.length) as |options|}} {{#list-item-text class="text-center"}} This project has no spiders {{/list-item-text}} {{/tree-list-item}} {{#tree-list-item hide=(or project.spiders.isPending project.spiders.length) class="help" as |options|}} {{/tree-list-item}} {{#if (and noCurrentSpider isLarge)}} {{#tree-list-item}} {{/tree-list-item}} {{/if}} {{#if (and noCurrentSpider hasPreviousPage)}} {{#tree-list-item isCentered=true}} {{/tree-list-item}} {{/if}}
    {{#each spiders as |spider|}} {{spider-row spider=spider project=project}} {{/each}}
    {{#if (and noCurrentSpider hasNextPage)}} {{#tree-list-item isCentered=true}} {{/tree-list-item}} {{/if}} {{/if}} {{/tree-list-item}} {{/tree-list}} {{#tree-list hide=currentSpider}} {{#tree-list-item hasChildren=true as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title"}} Data Format{{#animation-container class="inline" hide=currentSchema setHeight=false}}s{{/animation-container}} {{#animation-container class="inline" setHeight=false}} {{#help-icon}} Data Formats

    A data format describes the data that you want to extract.

    Spiders can share a data format to extract the same logical data type from different web pages.

    You can create data formats in advance, but you can also create them later, while annotating the data on a web page.

    {{/help-icon}} {{/animation-container}} {{/list-item-text}} {{#if currentSchema}} {{#animation-container}} {{#link-to 'projects.project' project class='inline project-change'}} Show all schemas {{/link-to}} {{/animation-container}} {{else}} {{#tooltip-container tooltipFor="add-schema-button" text="Create a new Schema" tooltipContainer='body'}} {{list-item-icon id="add-schema-button" icon='add' action=(action 'addSchema')}} {{/tooltip-container}} {{/if}} {{else if (eq options.section "subtrees")}} {{#tree-list-item hide=(or project.schemas.isPending project.schemas.length) as |options|}} {{#list-item-text class="text-center"}} This project has no data formats {{/list-item-text}} {{/tree-list-item}} {{#each project.schemas as |schema|}} {{#tree-list-item hide=(and currentSchema (not-eq schema currentSchema)) as |options|}} {{#link-to 'projects.project.schema' schema}} {{#if schema.default}} {{#help-icon icon='default-add' placement='right' classes='help-icon indentation-spacer'}} This Data Format will be used for new samples by default {{/help-icon}} {{else}} {{indentation-spacer}} {{/if}} {{list-item-icon icon='schema'}} {{list-item-editable value=(mut schema.name) editing=(mut schema.new) onChange=(action 'saveSchema' schema)}} {{/link-to}} {{#animation-container class="icon" setWidth=false setHeight=false}} {{#list-item-icon-menu icon='vertical-ellipsis' as |options|}} {{#if schema.default}}
  • {{list-item-icon class="icon" icon="default-remove"}}Remove as Default
  • {{else}}
  • {{list-item-icon class="icon" icon="default-add"}}Set as Default
  • {{/if}} {{dropdown-delete onDelete=(action 'removeSchema' schema) text='Delete Schema' disabled=(gt schema.items.length 0) }} {{/list-item-icon-menu}} {{/animation-container}} {{/tree-list-item}} {{/each}} {{/if}} {{/tree-list-item}} {{/tree-list}} ================================================ FILE: portiaui/app/templates/components/project-structure-spider-feed-url.hbs ================================================ {{#tree-list-item as |options|}} {{#link-to 'projects.project.spider.start-url.options' index bubbles=false}} {{indentation-spacer}} {{list-item-icon icon='url-feed'}} {{#list-item-text class="txt-describe"}}{{url}}{{/list-item-text}} {{#link-to 'projects.project.spider' bubbles=false}} {{#link-to 'projects.project.spider.start-url.options' index bubbles=false class="ignore-active" }} {{list-item-icon icon='options'}} {{/link-to}} {{/link-to}} {{list-item-icon icon='remove' action=(action removeStartUrl) bubbles=false}} {{/link-to}} {{/tree-list-item}} ================================================ FILE: portiaui/app/templates/components/project-structure-spider-generated-url.hbs ================================================ {{#tree-list-item as |options|}} {{#link-to 'projects.project.spider.start-url.options' index bubbles=false}} {{indentation-spacer}} {{list-item-icon icon='url-generated'}} {{#list-item-text class="generated-url"}}{{url}}{{/list-item-text}} {{#link-to 'projects.project.spider' bubbles=false}} {{#link-to 'projects.project.spider.start-url.options' index bubbles=false class="ignore-active"}} {{list-item-icon icon='options'}} {{/link-to}} {{/link-to}} {{list-item-icon icon='remove' action=(action removeStartUrl) bubbles=false}} {{/link-to}} {{/tree-list-item}} ================================================ FILE: portiaui/app/templates/components/project-structure-spider-url.hbs ================================================ {{#tree-list-item as |options|}} {{#link-to 'projects.project.spider' spider (query-params url=url baseurl=null) active=false}} {{indentation-spacer}} {{list-item-icon icon='url'}} {{list-item-editable value=(mut viewUrl) editing=(mut urlAdded) spellcheck=false}} {{list-item-icon icon='remove' action=(action removeStartUrl) bubbles=false}} {{/link-to}} {{/tree-list-item}} ================================================ FILE: portiaui/app/templates/components/regex-pattern-list.hbs ================================================ {{#tree-list}} {{#if list.length}} {{#each list as |item index|}} {{#tree-list-item hasChildren=spider.startUrls.length as |options|}} {{list-item-editable value=item spellcheck=false onChange=(action 'changePattern' index)}} {{list-item-icon icon='remove' action=(action 'removePattern' index)}} {{/tree-list-item}} {{/each}} {{else}} {{#tree-list-item hasChildren=spider.startUrls.length as |options|}} No patterns defined {{/tree-list-item}} {{/if}} {{/tree-list}}
    {{input type='text' class="form-control" placeholder="Regular expression" spellcheck=false value=(mut newPattern) change=(action 'stopPropagation') escape-press=(action 'clearPattern') insert-newline=(action 'addPattern')}} {{icon-button icon='add' disabled=(or (not newPattern) (not newPatternCorrect)) action=(action 'addPattern' newPattern)}}
    The input value is not a valid regular expression.
    ================================================ FILE: portiaui/app/templates/components/save-status.hbs ================================================ {{#tooltip-container tooltipFor=(concat "label-" elementId) tooltipContainer='body' as |tooltip|}} {{#if (eq tooltip.section 'tooltip')}}

    Every change you make is automatically saved by Portia

    {{else}} {{#if isSaving}} Saving ... {{else if timeSinceLastSave}} Last saved {{timeSinceLastSave}} {{else}} Changes are saved automatically {{/if}} {{/if}} {{/tooltip-container}} ================================================ FILE: portiaui/app/templates/components/schema-structure-listing.hbs ================================================ {{#tree-list}} {{#tree-list-item hasChildren=true as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title"}} Fields {{#help-icon}} Fields

    A field describes the type of a value that you want to extract.

    Sample pages map the elements of a web page to the individual fields of a data format.

    You can create fields in advance, but you can also create them later, while annotating the data on a web page.

    {{/help-icon}} {{/list-item-text}} {{#tooltip-container tooltipFor="add-field-button" text="Add field" tooltipContainer='body'}} {{list-item-icon id="add-field-button" icon='add' action=(action 'addField')}} {{/tooltip-container}} {{else if (eq options.section "subtrees")}} {{#tree-list-item hide=(or schema.fields.isPending schema.fields.length) as |options|}} {{#list-item-text class="text-center"}} This data format has no fields {{/list-item-text}} {{/tree-list-item}} {{#each schema.fields as |field|}} {{#tree-list-item as |options|}} {{#link-to 'projects.project.schema.field' field}} {{indentation-spacer}} {{list-item-icon icon=field.type}} {{list-item-editable value=(mut field.name) editing=(mut field.new) onChange=(action 'saveField' field) validate=(action 'validateFieldName' field)}} {{#list-item-field-type field=field}} Change field type {{/list-item-field-type}} {{#link-to 'projects.project.schema.field.options' field bubbles=false class="ignore-active"}} {{list-item-icon icon='options'}} {{/link-to}} {{list-item-icon icon='remove' disabled=(not (not field.annotations.length)) action=(action 'removeField' field) bubbles=false}} {{/link-to}} {{/tree-list-item}} {{/each}} {{/if}} {{/tree-list-item}} {{/tree-list}} ================================================ FILE: portiaui/app/templates/components/scrapinghub-links.hbs ================================================
  • Portia 2.0 Documentation
  • ================================================ FILE: portiaui/app/templates/components/select-box.hbs ================================================ {{#dropdown-widget class="select-box" open=(mut open) active=(mut viewValue) focused=value menuContainer=menuContainer menuClass=menuClass menuAlign=menuAlign isDisabled=isDisabled onClick=(action 'menuClicked') onClose=(action 'menuClosed') as |widget|}} {{#if (eq widget.section 'widget')}} {{else if (eq widget.section 'menu')}} {{#if hasBlock}} {{yield (hash menu=widget.menu header=widget.header item=widget.item divider=widget.divider setValue=(action 'setValue') setViewValue=(action 'setViewValue') setValueAndClose=(action 'setValueAndClose') closeMenu=widget.closeMenu)}} {{else}} {{#each choices as |choice|}} {{#widget.item value=choice action=(action 'setValueAndClose' choice)}} {{#if valueAttribute}} {{get choice valueAttribute}} {{else}} {{choice}} {{/if}} {{/widget.item}} {{/each}} {{/if}} {{/if}} {{/dropdown-widget}} ================================================ FILE: portiaui/app/templates/components/show-links-button.hbs ================================================ {{#tooltip-container tooltipFor="show-links-button" text="Toggle link highlighting" tooltipContainer='body' as |options|}} {{/tooltip-container}} ================================================ FILE: portiaui/app/templates/components/show-links-legend.hbs ================================================ {{#tree-list}} {{#tree-list-item as |options|}} {{list-item-badge value=followedLinks color=colors.green}} Followed {{/tree-list-item}} {{#tree-list-item as |options|}} {{list-item-badge value=jsLinks color=colors.blue}} Followed when Javascript is enabled {{/tree-list-item}} {{#tree-list-item as |options|}} {{list-item-badge value=ignoredLinks color=colors.red}} Not Followed {{/tree-list-item}} {{/tree-list}} ================================================ FILE: portiaui/app/templates/components/sliding-main.hbs ================================================ {{yield}} ================================================ FILE: portiaui/app/templates/components/spider-indentation.hbs ================================================ {{indentation-spacer}} ================================================ FILE: portiaui/app/templates/components/spider-message.hbs ================================================ {{#if hasSpider}} {{#tooltip-container tooltipFor='run-spider-button' text='Run this spider.' tooltipContainer='body'}} {{list-item-icon id='run-spider-button' icon='play' action=(action 'runSpider' currentSpider)}} {{/tooltip-container}} {{/if}} ================================================ FILE: portiaui/app/templates/components/spider-options.hbs ================================================

    Initialization

    {{#if spider.performLogin}}
    {{input type="url" class="form-control" id="loginUrl" value=(mut spider.loginUrl)}}
    {{input type="text" class="form-control" id="loginUser" value=(mut spider.loginUser)}}
    {{input type="text" class="form-control" id="loginPassword" value=(mut spider.loginPassword)}}
    {{/if}}

    Javascript support

    {{#if spider.jsEnabled}}
    Enable Javascript for URLs that match these patterns
    {{regex-pattern-list list=spider.jsEnablePatterns onChange=(action 'save')}}
    Disable Javascript for URLs that match these patterns
    {{regex-pattern-list list=spider.jsDisablePatterns onChange=(action 'save')}} {{/if}}
    ================================================ FILE: portiaui/app/templates/components/spider-row.hbs ================================================ {{#tree-list-item hide=(and currentSpider (not-eq spider currentSpider)) as |options|}} {{#link-to 'projects.project.spider' spider (query-params url=(or spider.firstUrl null) baseurl=null) current-when='projects.project.spider'}} {{spider-indentation spider=spider currentSpider=currentSpider}} {{list-item-icon icon='spider'}} {{#if currentSpider}} {{#list-item-text}}{{spider.nameAlias}}{{/list-item-text}} {{else}} {{list-item-editable value=(mut spider.nameAlias) onChange=(action 'saveSpiderName' spider) validate=(action 'validateSpiderName' spider)}} {{/if}} {{/link-to}} {{#animation-container class="icon" setWidth=false setHeight=false}} {{#list-item-icon-menu icon='vertical-ellipsis' as |options|}}
  • {{list-item-icon class="icon" icon="download"}}Download as Portia
  • {{list-item-icon class="icon" icon="code"}}Download as Scrapy
  • {{#if isCopyingSpider}} {{project-list projects=projects withinDropdown=true onClear=(action 'closeSpiderOptions') selectProject=(action 'copyToProject' options) }} {{else}} {{#options.item value="Copy" action=(action 'copySpider') as |value|}} {{list-item-icon class="icon" icon="copy"}}{{value}} {{/options.item}} {{/if}} {{dropdown-delete onDelete=(action 'removeSpider' spider) text='Delete Spider' }} {{/list-item-icon-menu}} {{/animation-container}} {{#animation-container class="icon" hide=(not-eq spider currentSpider) setWidth=false setHeight=false}} {{#tooltip-container tooltipFor=(concat "spider-options-button" (guid spider)) text="Advanced spider options" tooltipContainer='body'}} {{#link-to 'projects.project.spider' id=(concat "spider-options-button" (guid spider)) bubbles=false}} {{#link-to 'projects.project.spider.options' bubbles=false class="ignore-active"}} {{list-item-icon icon='options'}} {{/link-to}} {{/link-to}} {{/tooltip-container}} {{/animation-container}} {{/tree-list-item}} ================================================ FILE: portiaui/app/templates/components/spider-structure-listing.hbs ================================================ {{#tree-list hide=currentSample}} {{#tree-list-item hasChildren=true as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title"}} Start Pages {{#help-icon}} Start Pages

    Start pages are web pages that a spider will begin its crawl from. It will then continue to other web pages according to the defined link crawling rules.

    Start pages also restrict the domains that a spider will crawl. A spider will never follow a link that goes to a domain not included in the start pages.

    Without a start page the spider cannot begin crawling.

    {{/help-icon}} {{/list-item-text}} {{#tooltip-container tooltipFor="add-start-url-button" text="Start crawling from the current page" tooltipContainer='body'}} {{#list-item-icon-menu icon='add-dropdown' as |options|}} {{#options.item value="Add fixed URL" action=(chain-actions (action closeOptions) (action 'addStartUrl') options.closeMenu) as |value|}} {{list-item-icon class="icon" icon="url"}}{{value}} {{/options.item}} {{#options.item value="Add generation URL" action=(chain-actions (action 'addGenerationUrl') options.closeMenu) as |value|}} {{list-item-icon class="icon" icon="url-generated"}}{{value}} {{/options.item}} {{#options.item value="Add feed URL" action=(chain-actions (action closeOptions) (action 'addFeedUrl') options.closeMenu) as |value|}} {{list-item-icon class="icon" icon="url-feed"}}{{value}} {{/options.item}} {{/list-item-icon-menu}} {{/tooltip-container}} {{else if (eq options.section "subtrees")}} {{#tree-list-item hide=spider.startUrls.length as |options|}} {{#list-item-text class="text-center"}} This spider has no start pages {{/list-item-text}} {{/tree-list-item}} {{#tree-list-item hide=spider.startUrls.length class="help" as |options|}} {{/tree-list-item}} {{#each spider.startUrls key="@index" as |startUrl index|}} {{#if (or (not newUrl) (not-eq urlValue startUrl.url))}} {{component startUrl.componentName index=index spider=spider startUrl=startUrl removeStartUrl=(action 'removeStartUrl' startUrl) }} {{/if}} {{/each}} {{#if newUrl}} {{project-structure-spider-url spider=spider startUrl=newStartUrl url=urlValue urlAdded=(mut newUrl) removeStartUrl=(action 'removeStartUrl' newUrl) }} {{/if}} {{/if}} {{/tree-list-item}} {{/tree-list}} {{#tree-list hide=currentSample}} {{#tree-list-item hasChildren=true as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title"}} Link Crawling {{/list-item-text}} {{else if (eq options.section "subtrees")}} {{#tree-list-item as |options|}} {{indentation-spacer}} {{list-item-icon icon='link'}} {{list-item-link-crawling spider=spider}} {{#if (not-eq spider.linksToFollow 'none')}} {{#link-to 'projects.project.spider' bubbles=false}} {{#link-to 'projects.project.spider.link-options' bubbles=false class="ignore-active"}} {{list-item-icon icon='options'}} {{/link-to}} {{/link-to}} {{/if}} {{/tree-list-item}} {{/if}} {{/tree-list-item}} {{/tree-list}} {{#tree-list}} {{#tree-list-item hasChildren=true as |options|}} {{#if (eq options.section "item")}} {{#list-item-text class="title"}} Sample Page{{#animation-container class="inline" hide=currentSample setHeight=false}}s{{/animation-container}} {{#animation-container class="inline" setHeight=false}} {{#help-icon}} Sample Pages

    A sample page is a web page with the data you want to extract annotated.

    When the spider crawls to a new web page it finds the sample page that is the best match, and uses it to extract data.

    If you see a web page that the spider is having trouble extracting data from, you can create a new sample page from that web page to improve the extraction.

    {{/help-icon}} {{/animation-container}} {{/list-item-text}} {{#if currentSample}} {{#animation-container}} {{#link-to 'projects.project.spider' spider}} Show all samples {{/link-to}} {{/animation-container}} {{else}} {{#tooltip-container tooltipFor="add-sample-button" text="Create a new sample from the current page" tooltipContainer='body'}} {{list-item-icon id="add-sample-button" icon='add' disabled=(not canAddSample) action=(action 'addSample')}} {{/tooltip-container}} {{/if}} {{else if (eq options.section "subtrees")}} {{#tree-list-item hide=(or spider.samples.isPending spider.samples.length) as |options|}} {{#list-item-text class="text-center"}} This spider has no sample pages {{/list-item-text}} {{/tree-list-item}} {{#tree-list-item hide=(or spider.samples.isPending spider.samples.length) class="help" as |options|}} {{/tree-list-item}} {{#each spider.samples as |sample|}} {{#tree-list-item hide=(and currentSample (not-eq sample currentSample)) as |options|}} {{#link-to 'projects.project.spider.sample' sample (query-params url=sample.url baseurl=null) current-when='projects.project.spider.sample'}} {{indentation-spacer}} {{list-item-icon icon='sample'}} {{list-item-editable value=(mut sample.name) editing=(mut sample.new) onChange=(action 'saveSample' sample)}} {{/link-to}} {{#list-item-icon-menu icon='vertical-ellipsis' as |options|}} {{dropdown-delete onDelete=(action 'removeSample' sample) text='Delete Sample' }} {{/list-item-icon-menu}} {{/tree-list-item}} {{/each}} {{/if}} {{/tree-list-item}} {{/tree-list}} ================================================ FILE: portiaui/app/templates/components/start-url-options.hbs ================================================ {{#tool-group id="fragments-options-group" collapsible=false onClose=(route-action 'closeOptions') as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="annotation-options"}}{{title}}{{/group.tab}} {{else if (eq group.section "panels")}} {{#group.panel class="extracted-items container-fluid" toolId="annotation-options" as |active|}} {{component startUrl.optionsComponentName spider=spider startUrl=startUrl saveSpider=saveSpider }} {{/group.panel}} {{/if}} {{/tool-group}} ================================================ FILE: portiaui/app/templates/components/tool-group.hbs ================================================
    {{yield (hash section="panels" group=this tab=(component 'tool-tab' group=this) panel=(component 'tool-panel' group=this))}}
    ================================================ FILE: portiaui/app/templates/components/tool-panel.hbs ================================================
    {{yield active}}
    ================================================ FILE: portiaui/app/templates/components/tool-tab.hbs ================================================ {{yield active}} ================================================ FILE: portiaui/app/templates/components/tooltip-container.hbs ================================================ {{yield (hash section='body')}} ================================================ FILE: portiaui/app/templates/components/tooltip-icon.hbs ================================================ {{#tooltip-container tooltipFor=elementId text=text tooltipContainer='body' }} {{icon-button id=elementId icon=icon modifyClasses=modifyClasses action=(action 'onClick') }} {{/tooltip-container}} ================================================ FILE: portiaui/app/templates/components/tree-list-item-row.hbs ================================================
    {{yield}}
    ================================================ FILE: portiaui/app/templates/components/tree-list-item.hbs ================================================
    {{#tree-list-item-row isCentered=isCentered onMouseEnter=onMouseEnter onMouseLeave=onMouseLeave }} {{yield (hash section="item")}} {{/tree-list-item-row}} {{#if hasChildren}} {{#tree-list}} {{yield (hash section="subtrees")}} {{/tree-list}} {{/if}}
    ================================================ FILE: portiaui/app/templates/components/tree-list.hbs ================================================
      {{yield}}
    ================================================ FILE: portiaui/app/templates/components/url-bar.hbs ================================================
    {{#tooltip-container tooltipFor="mode-feedback-icon" tooltipContainer='body' placement='right' as |options|}} {{#if (eq options.section 'tooltip')}} {{#if (eq mode 'navigation')}} Browsing

    You can interact with the web page in this mode.

    {{else if (eq mode 'data-annotation')}} Annotating

    Click on elements in the sample to create data annotations.

    Close the sample to switch back to navigating mode.

    {{/if}} {{else}} {{/if}} {{/tooltip-container}}
    {{buffered-input placeholder="Enter a website address" value=(mut url) viewValue=(mut editedUrl) autofocus=autofocus autoSelect=true disabled=disabled spellcheck=false onEnterPress=(action 'submit')}}
    ================================================ FILE: portiaui/app/templates/options-panels.hbs ================================================ ================================================ FILE: portiaui/app/templates/projects/project/conflicts/file-selector.hbs ================================================ ================================================ FILE: portiaui/app/templates/projects/project/conflicts/help.hbs ================================================
    {{#if conflictedFiles}}

    Aw, Snap!

    Portia couldn't deploy the project because there are conflicts with another user's changes

    Resolve the conflicts manually by selecting the conflicting files from the left panel to deploy the project.

    {{else}}

    All done

    All conflicts are resolved, to continue, go back to the {{link-to "project page" 'projects.project' projectController.model}} and try to deploy again.

    {{/if}}
    ================================================ FILE: portiaui/app/templates/projects/project/conflicts/resolver.hbs ================================================
    {{json-file-compare json=model.contents update="updateConflict"}}
    ================================================ FILE: portiaui/app/templates/projects/project/conflicts/topbar.hbs ================================================ ================================================ FILE: portiaui/app/templates/projects/project/schema/field/options.hbs ================================================ {{#tool-group id="field-options-group" collapsible=false onClose=(action 'closeOptions') as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="field-options"}} Field properties {{/group.tab}} {{else if (eq group.section "panels")}} {{#group.panel class="extracted-items container-fluid" toolId="field-options" as |active|}} {{field-options field=model}} {{/group.panel}} {{/if}} {{/tool-group}} ================================================ FILE: portiaui/app/templates/projects/project/schema/field.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/schema/structure.hbs ================================================ {{schema-structure-listing schema=model}} ================================================ FILE: portiaui/app/templates/projects/project/schema.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/spider/link-options.hbs ================================================ {{#tool-group id="link-crawling-options-group" collapsible=false onClose=(action 'closeOptions') as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="link-crawling-options"}} Link crawling options {{/group.tab}} {{else if (eq group.section "panels")}} {{#group.panel class="extracted-items container-fluid" toolId="link-crawling-options" as |active|}} {{link-crawling-options spider=model}} {{/group.panel}} {{/if}} {{/tool-group}} ================================================ FILE: portiaui/app/templates/projects/project/spider/options.hbs ================================================ {{#tool-group id="spider-options-group" collapsible=false onClose=(action 'closeOptions') as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="spider-options"}} Spider properties {{/group.tab}} {{else if (eq group.section "panels")}} {{#group.panel class="extracted-items container-fluid" toolId="spider-options" as |active|}} {{spider-options spider=model}} {{/group.panel}} {{/if}} {{/tool-group}} ================================================ FILE: portiaui/app/templates/projects/project/spider/overlays.hbs ================================================ {{#if model.showLinks}}
    {{#each linkOverlayElements key="guid" as |overlay|}} {{element-overlay viewPortElement=overlay.element color=overlay.color}} {{/each}}
    {{/if}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/annotation/selection.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/data/annotation/options.hbs ================================================ {{#tool-group id="annotation-options-group" collapsible=false onClose=(action 'closeOptions') as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="annotation-options"}} Annotation properties {{/group.tab}} {{else if (eq group.section "panels")}} {{#group.panel class="extracted-items container-fluid" toolId="annotation-options" as |active|}} {{annotation-options annotation=model}} {{field-options field=model.field.content}} {{extractor-options annotation=model}} {{/group.panel}} {{/if}} {{/tool-group}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/data/annotation.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/data/item.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/data/overlays.hbs ================================================
    {{#each sample.dataStructure.elements.all as |element|}} {{#each (get sample.dataStructure.annotations (guid element)) as |annotation|}} {{#if (eq annotation.constructor.modelName "annotation")}} {{element-overlay class=(concat (if (eq element hoveredElement) 'hovered') (if (includes hoveredModels annotation) ' group-hovered') (if (and (eq element selectedElement) (eq selectedModel annotation)) ' selected') (if (eq selectedModel annotation) ' group-selected')) viewPortElement=element icon=(if (eq element hoveredElement) (get selectionModeIcons activeSelectionMode)) color=(array-get annotationColors annotation.orderedIndex)}} {{/if}} {{/each}} {{/each}} {{element-overlay class=(concat 'hover-overlay' (unless showHoverOverlay ' hide')) positionMode='edges' viewPortElement=hoveredElement icon=(get selectionModeIcons activeSelectionMode) color=hoverOverlayColor}}
    ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/data/structure.hbs ================================================ {{data-structure-listing sample=model annotationColors=annotationColors}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/data/toolbar.hbs ================================================ Tools
    {{#tooltip-container tooltipFor="css-tool-button" placement='left' tooltipContainer='body' as |options| }} {{#if (eq options.section 'tooltip')}} Toggle page styling

    When page styling is enabled you see the web page as the page author intended, the same way it would appear in a browser. However, sometimes this makes it hard to select the data that you need, for example if there are overlapping parts of the page or if some parts are hidden.

    You can disable the page styling which will change the look and layout of the page but will force all content within the page to become visible.

    {{else}} {{/if}} {{/tooltip-container}}
    {{#tooltip-container tooltipFor="magic-tool-button" placement='left' tooltipContainer='body' as |options| }} {{#if (eq options.section 'tooltip')}} Magic tool selector

    When the magic tool selector is enabled, it will attempt to choose the most useful tool for you automatically, based on the element you are pointing at in the web page.

    You can see which tool is being selected for you by looking at enabled tool selection button, and at the icon visible on the element under the cursor.

    If you need, you can manually change the tool for the next click, by switching to it using the tool selection buttons.

    {{else}} {{/if}} {{/tooltip-container}}
    {{#each-in selectionModeIcons as |mode icon|}} {{#tooltip-container tooltipFor=(get selectionModeIds mode) tooltipContainer='body' text=(get selectionModeText mode) }} {{/tooltip-container}} {{/each-in}}
    ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/data/tools.hbs ================================================ {{#tool-group id="inspector-group" as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="inspector"}} Inspector {{/group.tab}} {{else if (eq group.section "panels")}} {{#group.panel class="inspector container-fluid" toolId="inspector"}} {{inspector-panel sample=model annotationColors=annotationColors}} {{/group.panel}} {{/if}} {{/tool-group}} {{extracted-items-group}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/data.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/item.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/structure.hbs ================================================ {{outlet 'sample-structure'}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample/toolbar.hbs ================================================ {{outlet 'browser-toolbar'}} {{#tooltip-container tooltipFor="sample-close-button-browser" text="Finish editing your sample so you can continue browsing and see how it works on other pages" tooltipContainer='body'}} {{#link-to 'projects.project.spider' class="btn btn-primary" activeClass="" id="sample-close-button-browser"}} {{icon-button icon='close'}} Close sample {{/link-to}} {{/tooltip-container}} ================================================ FILE: portiaui/app/templates/projects/project/spider/sample.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/spider/start-url/options.hbs ================================================ {{start-url-options spider = model.spider startUrlId = model.startUrlId }} ================================================ FILE: portiaui/app/templates/projects/project/spider/structure.hbs ================================================ {{spider-structure-listing project=model.project spider=model closeOptions=(route-action 'closeOptions') transitionToFragments=(route-action 'transitionToFragments') }} {{outlet 'spider-structure'}} ================================================ FILE: portiaui/app/templates/projects/project/spider/toolbar.hbs ================================================ {{show-links-button spider=model}} {{add-start-url-button spider=model}} {{edit-sample-button spider=model}} ================================================ FILE: portiaui/app/templates/projects/project/spider/tools.hbs ================================================ {{#if model.showLinks}} {{#tool-group id="show-links-legend-group" as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="show-links-legend"}} Followed links {{/group.tab}} {{else if (eq group.section "panels")}} {{#group.panel id="show-links-legend" class="container-fluid" toolId="show-links-legend"}} {{show-links-legend followedLinks=followedLinkElements.length jsLinks=jsLinkElements.length ignoredLinks=ignoredLinkElements.length}} {{/group.panel}} {{/if}} {{/tool-group}} {{/if}} {{!-- {{#tool-group id="actions-group" as |group|}} {{#if (eq group.section "tabs")}} {{#group.tab toolId="actions"}} Actions {{/group.tab}} {{else if (eq group.section "panels")}} {{#group.panel class="actions container-fluid" toolId="actions"}} {{page-actions-editor pageActions=model.pageActions}} {{/group.panel}} {{/if}} {{/tool-group}} --}} {{extracted-items-group}} ================================================ FILE: portiaui/app/templates/projects/project/spider.hbs ================================================ {{outlet}} ================================================ FILE: portiaui/app/templates/projects/project/structure.hbs ================================================ ================================================ FILE: portiaui/app/templates/projects/project/toolbar.hbs ================================================ {{create-spider-button project=model}} ================================================ FILE: portiaui/app/templates/projects/project.hbs ================================================ {{#browser-view-port clickHandler=(action "viewPortClick") as |options|}} {{#if (eq options.section "toolbar")}} {{outlet "browser-toolbar"}} {{else if (eq options.section "overlays")}} {{outlet "browser-overlays"}} {{/if}} {{/browser-view-port}} ================================================ FILE: portiaui/app/templates/projects.hbs ================================================
    Portia logo

    What would you like to work on today?

    {{create-project-button projects=model}} {{#if model}}

    Choose a project from the list below.

    {{project-list projects=model}} {{/if}}
    ================================================ FILE: portiaui/app/templates/tool-panels.hbs ================================================ ================================================ FILE: portiaui/app/transforms/array.js ================================================ import DS from 'ember-data'; export default DS.Transform.extend({ deserialize: function(serialized) { if (Array.isArray(serialized)) { return serialized; } return []; }, serialize: function(deserialized) { if (Array.isArray(deserialized)) { return deserialized; } return []; } }); ================================================ FILE: portiaui/app/transforms/json.js ================================================ import DS from 'ember-data'; export default DS.Transform.extend({ deserialize: function(serialized) { return JSON.parse(serialized); }, serialize: function(deserialized) { return JSON.stringify(deserialized); } }); ================================================ FILE: portiaui/app/transforms/start-url.js ================================================ import DS from 'ember-data'; import buildStartUrl from '../models/start-url'; export default DS.Transform.extend({ deserialize: function(serialized) { if (Array.isArray(serialized)) { return serialized.map((url) => buildStartUrl(url)); } return []; }, serialize: function(deserialized) { if (Array.isArray(deserialized)) { return deserialized.map((startUrl) => startUrl.serialize()); } return []; } }); ================================================ FILE: portiaui/app/utils/attrs.js ================================================ import Ember from 'ember'; export function attrValue(attr) { return (!Ember.isNone(attr) && typeof attr === 'object' && 'value' in attr) ? attr.value : attr; } export function attrChanged(oldAttrs, newAttrs, key) { return !oldAttrs || attrValue(oldAttrs[key]) !== attrValue(newAttrs[key]); } export function attrChangedTo(oldAttrs, newAttrs, key, value) { return attrChanged(oldAttrs, newAttrs, key) && attrValue(newAttrs[key]) === value; } export default { attrValue, attrChanged, attrChangedTo }; ================================================ FILE: portiaui/app/utils/browser-features.js ================================================ import Ember from 'ember'; const { RSVP } = Ember; export default function hasBrowserFeatures() { // generatedcontent: detection issue with zoom in chrome let features = [ "eventlistener", "json", "postmessage", "queryselector", "requestanimationframe", "svg", "websockets", "cssanimations", "csscalc", "flexbox", "nthchild", "csspointerevents", "opacity", "csstransforms", "csstransitions", "cssvhunit", "classlist", "placeholder", "localstorage", "svgasimg", "datauri", "atobbtoa" ]; let feature_promises = features.map((feature) => { return new RSVP.Promise((resolve) => { Modernizr.on(feature, (isFeatureActive) => { resolve(isFeatureActive); }); }); }); return RSVP.all(feature_promises); } ================================================ FILE: portiaui/app/utils/colors.js ================================================ import Ember from 'ember'; // material design colours export const COLORS = [ { name: 'indigo', main: '#3f51b5', shadow: '#1a237e' }, { name: 'blue', main: '#2196f3', shadow: '#0d47a1' }, { name: 'light blue', main: '#03a9f4', shadow: '#01579b' }, { name: 'cyan', main: '#00bcd4', shadow: '#006064' }, { name: 'teal', main: '#009688', shadow: '#004d40' }, { name: 'green', main: '#4caf50', shadow: '#1b5e20' }, { name: 'light green', main: '#8bc34a', shadow: '#33691e' }, { name: 'lime', main: '#cddc39', shadow: '#827717' }, { name: 'yellow', main: '#ffeb3b', shadow: '#f57f17' }, { name: 'amber', main: '#ffc107', shadow: '#ff6f00' }, { name: 'orange', main: '#ff9800', shadow: '#e65100' }, { name: 'deep orange', main: '#ff5722', shadow: '#bf360c' }, { name: 'red', main: '#f44336', shadow: '#b71c1c' }, { name: 'pink', main: '#e91e63', shadow: '#880e4f' }, { name: 'purple', main: '#9c27b0', shadow: '#4a148c' }, { name: 'deep purple', main: '#673ab7', shadow: '#311b92' } ]; export const NAMED_COLORS = {}; for (let color of COLORS) { NAMED_COLORS[color.name] = color; } export function interpolate(start, end, fraction) { return { main: Ember.$.Color(start.main).transition( Ember.$.Color(end.main), fraction ).toHexString(), shadow: Ember.$.Color(start.shadow).transition( Ember.$.Color(end.shadow), fraction ).toHexString() }; } function* generateInterpolatedColors(n) { // use as many colors as required interpolated between the pre-defined colors const spacePerColor = COLORS.length / n; for (let i = 0; i < n; i++) { var prevIndex = Math.floor(i * spacePerColor); var nextIndex = Math.ceil(i * spacePerColor); if (prevIndex === nextIndex) { yield COLORS[prevIndex]; } yield interpolate( COLORS[prevIndex], COLORS[nextIndex] || COLORS[0], i * spacePerColor - prevIndex); } } export function getColors(n) { if (n <= COLORS.length >> 1) { // use every second color return COLORS.filter((color, index) => index % 2 === 0).slice(0, n); } else if (n <= COLORS.length) { // use all available colors return COLORS.slice(0, n); } return Array.from(generateInterpolatedColors(n)); } ================================================ FILE: portiaui/app/utils/computed.js ================================================ import Ember from 'ember'; export function computedPropertiesEqual(a, b) { return Ember.computed(a, b, function() { return this.get(a) === this.get(b); }); } ================================================ FILE: portiaui/app/utils/ensure-promise.js ================================================ import Ember from 'ember'; // http://stackoverflow.com/questions/28247401/how-can-i-test-if-a-function-is-returning-a-promise-in-ember export default function ensurePromise(x) { return new Ember.RSVP.Promise(function(resolve) { resolve(x); }); } ================================================ FILE: portiaui/app/utils/interaction-event.js ================================================ var eventCategories = { "keyup": "keyboard", "keydown": "keyboard", "keypress": "keyboard", "mousedown": "mouse", "mouseup": "mouse", "click": "mouse", "scroll": "scroll", "focus": "focus", "blur": "focus", "input": "simple", "change": "simple", }; function getEventCategory (evt) { if(evt.type in eventCategories) { return eventCategories[evt.type]; } throw new Error("Can't serialize event of type " + evt.type); } var interactionEvent = function(evt) { var target = evt.target; var doc = target.ownerDocument; if(target && target.nodeType === Node.DOCUMENT_NODE){ doc = target; target = doc.documentElement; } if(!target || !target.nodeid) { return null; } var data = { category: getEventCategory(evt.originalEvent || evt), type: evt.type, target: target.nodeid, propsBefore: {}, propsAfter: {} }; if(data.category === 'mouse') { // Send coordinates as a offset of the element instead of the document var clientRect = target.getBoundingClientRect(); data.targetX = evt.clientX - clientRect.left; data.targetY = evt.clientY - clientRect.top; data.relatedTarget = evt.relatedTarget && evt.relatedTarget.nodeid; } else if (data.type === 'scroll') { let scrollTarget = target; // Scroll events in the body are dispatched in the document, reverse if(scrollTarget === doc.documentElement && !(target.scrollTopMax || target.scrollLeftMax)) { scrollTarget = doc.body; } if (scrollTarget) { data.scrollTop = scrollTarget.scrollTop; data.scrollTopPercent = scrollTarget.scrollTopMax && Math.round(scrollTarget.scrollTop * 100 / scrollTarget.scrollTopMax); data.scrollLeft = scrollTarget.scrollLeft; } else { data.scrollTop = 0; data.scrollLeft = 0; data.scrollTopPercent = 0; } } ATTRIBUTE_WHITELIST.forEach((attr) => { if (attr in evt) { data[attr] = evt[attr]; } }); function copyProperties(update_props, obj){ if(evt.type in update_props) { update_props[evt.type].forEach(function(propName){ if(propName in target) { obj[propName] = target[propName]; } }); } } copyProperties(UPDATE_PROPS_BEFORE, data.propsBefore); copyProperties(UPDATE_PROPS_AFTER, data.propsAfter); return data; }; var ATTRIBUTE_WHITELIST = [ 'altKey', 'bubbles', 'button', 'buttons', 'cancelable', 'code', 'ctrlKey', 'deltaX', 'deltaY', 'deltaZ', 'deltaMode', 'detail', 'isComposing', 'isTrusted', 'key', 'keyCode', 'location', 'metaKey', 'relatedTargetId', 'shiftKey', 'type' ]; // When this events are fired, update the specified properties in the server // to the ones in the client before sending the event var UPDATE_PROPS_BEFORE = { 'change': ['selectedIndex'], // selects 'input': ['value'], // text input, textareas 'keyup': ['value'], // text input, textareas 'click': ['checked'] // input type radio or check }; var UPDATE_PROPS_AFTER = { 'keydown': ['value'], // text input, textareas 'keypress': ['value'] // text input, textareas }; export default interactionEvent; ================================================ FILE: portiaui/app/utils/promises.js ================================================ import Ember from 'ember'; export function ensurePromise(valueOrPromise) { return new Ember.RSVP.Promise(function(resolve) { resolve(valueOrPromise); }); } export default { ensurePromise }; ================================================ FILE: portiaui/app/utils/selectors.js ================================================ import Ember from "ember"; const { computed, guidFor } = Ember; const IMPLICIT_TAGS = new Set(['tbody']); let escapeCSS = CSS.escape; export function elementPath(element) { const elements = [element]; while (element.parentElement && !element.parentElement.isEqualNode(document.documentElement)) { element = element.parentElement; elements.unshift(element); } return elements; } function positionInParent(element) { return Array.prototype.indexOf.call(element.parentNode.children, element) + 1; } export function pathSelector(element) { const path = elementPath(element); return path.map(pathElement => pathElement.tagName.toLowerCase()).join(' > '); } export function uniquePathSelector(element) { const path = elementPath(element); return path.map((pathElement, index) => { const tag = pathElement.tagName.toLowerCase(); if (index === 0) { return tag; } const parentIndex = positionInParent(pathElement); return `${tag}:nth-child(${parentIndex})`; }).join(' > '); } export function smartSelector(element) { const generator = BaseSelectorGenerator.create({ elements: [element] }); const selector = generator.get('selector'); generator.destroy(); return selector; } export function cssToXpath(selector) { // css-to-xpath on github fails on nth-child(an+b) selectors :( // this is mini version that supports only the css generated by BaseSelectorGenerator // rules from: https://en.wikibooks.org/wiki/XPath/CSS_Equivalents // TODO: support CSS escaped identifiers const alternateSelectors = selector.split(', '); const alternateXPaths = []; for (let alternateSelector of alternateSelectors) { const selectorParts = alternateSelector.split(' > '); const xPathParts = []; for (let selectorPart of selectorParts) { const selectorSiblingParts = selectorPart.split(' + '); const xPathSiblingParts = []; for (let part of selectorSiblingParts) { // cases we need to support if (part === '*') { xPathSiblingParts.push('*[1]'); // id selector } else if (part.startsWith('#')) { xPathSiblingParts.push(`*[@id="${part.slice(1)}"]`); } else { let match; match = part.match(/^([a-z]+[0-9]?)?(?:\.((?:.(?!:nth-child))+.))?(?::nth-child\((\d+)\))?(?::nth-child\((\d*)n\+(\d+)\))?(?::nth-child\(-(\d*)n\+(\d+)\))?$/); // jshint ignore:line if (match) { let conditions = ''; // simple :nth-child selectors if (match[3]) { conditions += `[${match[3]}]`; } // complex :nth-child selectors if (match[5] || match[7]) { const delta = match[4] === undefined ? match[6] : match[4]; const start = match[5]; const end = match[7]; const modulus = (start === undefined ? end : start) % delta; let condition = `position() mod ${delta} = ${modulus}`; if (start && start > delta) { condition += ` and position() >= ${start}`; } if (end) { condition += ` and position() <= ${end}`; } conditions += `[${condition}]`; } // class selector if (match[2]) { conditions += `[contains(concat(" ", @class, " "), " ${match[2]} ")]`; } xPathSiblingParts.push(`${match[1] || '*'}${conditions}`); } } } xPathParts.push(xPathSiblingParts.join('/following-sibling::')); } alternateXPaths.push('//' + xPathParts.join('/')); } return alternateXPaths.join(' | '); } export const BaseSelectorGenerator = Ember.Object.extend({ parent: null, elements: [], siblings: null, paths: computed.map('elements', elementPath), groupedPaths: computed('paths', function() { const paths = this.get('paths'); return this.groupPaths(paths); }), parentMap: computed( 'parent', 'parent.groupedPaths', 'parent.selectors', 'parent.siblings', function() { if (!this.get('parent')) { return null; } const parentGroupedPaths = this.get('parent.groupedPaths') || []; const parentSelectors = this.get('parent.selectors') || []; const parentSiblings = this.get('parent.siblings') || 0; const parentMap = new Map(); for (let [index, paths] of parentGroupedPaths.entries()) { const pathSelectors = parentSelectors[index]; const siblingSelectors = [pathSelectors]; for (let i = 0; i < parentSiblings; i++) { siblingSelectors.push( siblingSelectors[siblingSelectors.length - 1].map( selector => `${selector} + *`)); } for (let path of paths) { let element = path[path.length - 1]; parentMap.set(element, pathSelectors); for (let i = 0; i < parentSiblings; i++) { element = element.nextElementSibling; if (!element) { break; } parentMap.set(element, siblingSelectors[i + 1]); } } } return parentMap; }), selectors: computed('groupedPaths', 'parentMap', function() { const groupedPaths = this.get('groupedPaths'); const parentMap = this.get('parentMap'); return this.createSelectors(groupedPaths, parentMap); }), selector: computed('selectors', function() { const selectors = this.get('selectors'); // filter out selectors with trailing implicit tags, if a selector // without the tag also exists, otherwise the combined selector may // match too many elements const filteredSelectors = []; for (let selectorGroup of selectors) { for (let selector of selectorGroup) { const selectorParts = selector.split(' > '); const trailingTag = selectorParts[selectorParts.length - 1]; if (!IMPLICIT_TAGS.has(trailingTag) || !selectorGroup.includes(selectorParts.slice(0, -1).join(' > '))) { filteredSelectors.push(selector); } } } return this.mergeSelectors(filteredSelectors); }), xpath: computed('selector', function() { const selector = this.get('selector'); return cssToXpath(selector); }), groupPaths(paths) { const groupedPaths = new Map(); for (let path of paths) { // group by full path of tags names, and root element const tagPath = [guidFor(path[0])].concat(path.map(element => element.tagName)) .join(' ').toLowerCase(); const list = groupedPaths.get(tagPath) || []; groupedPaths.set(tagPath, list); list.push(path); } return Array.from(groupedPaths.values()); }, createSelectors(groupedPaths, parentMap) { return groupedPaths.map(group => this.createGroupSelectors(group, parentMap)); }, createGroupSelectors(group, parentMap, generalize = false) { const root = group && group[0] && group[0][0]; let parentIndex = 0; let parentElements = null; let selectors = [root.tagName.toLowerCase()]; const pathLength = group[0].length; if (parentMap) { for (let i = 1; i < pathLength; i++) { if (parentMap.has(group[0][i])) { parentIndex = i; } } } if (parentIndex) { const elements = Array.from(new Set(group.map(path => path[parentIndex]))); parentElements = elements; selectors = parentMap.get(elements[0]); } let skippedTag = null; indexloop: for (let i = parentIndex + 1; i < pathLength; i++) { const elements = this.getGroupElementsAtIndex(group, i); const testSelectorLists = []; // check id selector if (elements.length === 1) { const id = elements[0].id; if (id && !parentElements) { testSelectorLists.push(['#' + escapeCSS(id)]); } } const tagName = elements[0].tagName.toLowerCase(); const classSelectors = this.getElementClassSelectors(elements); const allClassesSelector = tagName + classSelectors.join(''); if (!generalize) { // check class selectors for (let classSelector of classSelectors) { testSelectorLists.push([classSelector]); } // check tag selector if (!IMPLICIT_TAGS.has(tagName)) { testSelectorLists.push([tagName]); } // check tag + class selector for (let classSelector of classSelectors) { testSelectorLists.push([tagName + classSelector]); } } if (!IMPLICIT_TAGS.has(tagName)) { // nth-child const indices = this.getElementIndices(elements); if (indices.length > 1 && !generalize) { // try to create an nth-child formula let delta = indices[1] - indices[0]; let regularIndex = true; for (let i = 2; i < indices.length; i++) { if (indices[i] - indices[i - 1] !== delta) { regularIndex = false; } } if (regularIndex) { const firstIndex = indices[0]; const lastIndex = indices[indices.length - 1]; if (delta === 1) { delta = ''; } testSelectorLists.push( [`${tagName}:nth-child(${delta}n+${firstIndex})`], [`${tagName}:nth-child(-${delta}n+${lastIndex})`], [`${tagName}:nth-child(${delta}n+${firstIndex}):nth-child(-${delta}n+${lastIndex})`]); // jshint ignore:line for (let classSelector of classSelectors) { testSelectorLists.push( [`${classSelector}:nth-child(${delta}n+${firstIndex})`], [`${classSelector}:nth-child(-${delta}n+${lastIndex})`], [`${classSelector}:nth-child(${delta}n+${firstIndex}):nth-child(-${delta}n+${lastIndex})`]); // jshint ignore:line testSelectorLists.push( [`${tagName}${classSelector}:nth-child(${delta}n+${firstIndex})`], [`${tagName}${classSelector}:nth-child(-${delta}n+${lastIndex})`], [`${tagName}${classSelector}:nth-child(${delta}n+${firstIndex}):nth-child(-${delta}n+${lastIndex})`]); // jshint ignore:line } } } if (!generalize) { // fail-safe explicitly listing all indices let indexSelectors = []; for (let index of indices) { indexSelectors.push(`${tagName}:nth-child(${index})`); } testSelectorLists.push(indexSelectors); for (let classSelector of classSelectors) { let classIndexSelectors = []; let tagIndexSelectors = []; for (let index of indices) { const classIndexSelector = `${classSelector}:nth-child(${index})`; classIndexSelectors.push(classIndexSelector); tagIndexSelectors.push(`${tagName}${classIndexSelector}`); } testSelectorLists.push(classIndexSelectors); testSelectorLists.push(tagIndexSelectors); } } if (generalize && indices.length === 1) { testSelectorLists.push([`${allClassesSelector}:nth-child(${indices[0]})`]); } } if (generalize) { // fail-safe for generalized case testSelectorLists.push([allClassesSelector]); } if (!parentElements) { if (!generalize || elements.length === 1) { for (let testSelectorList of testSelectorLists) { const matches = root.querySelectorAll( this.mergeSelectors(testSelectorList)); if (matches.length === elements.length) { selectors = testSelectorList; continue indexloop; } } } } for (let testSelectorList of testSelectorLists) { const concatSelectorList = []; for (let selector of selectors) { for (let testSelector of testSelectorList) { concatSelectorList.push(`${selector} > ${testSelector}`); } } if (skippedTag) { // since we can't know in browser if the skipped tag was present in the source // markup we have at create a selector for both options like: // prefix > suffix, prefix > skipped > suffix for (let selector of selectors) { for (let testSelector of testSelectorList) { concatSelectorList.push( `${selector} > ${skippedTag} > ${testSelector}`); } } } const testSelector = this.mergeSelectors(concatSelectorList); let matches; if (parentElements) { matches = new Set(); for (let parentElement of parentElements) { for (let element of parentElement.querySelectorAll(testSelector)) { matches.add(element); } } matches = Array.from(matches); } else { matches = root.querySelectorAll(testSelector); } if (generalize || matches.length === elements.length) { selectors = concatSelectorList; skippedTag = null; continue indexloop; } } // we're here because we skipped a possibly implicitly added tag skippedTag = tagName; } // the final tag was skipped, we need to append it now if (skippedTag) { selectors = selectors.concat(...selectors.map( selector => `${selector} > ${skippedTag}`)); } return selectors; }, mergeSelectors(selectors) { while (Array.isArray(selectors)) { selectors = selectors.join(', '); } return selectors; }, getGroupElementsAtIndex(group, index) { return Array.from(new Set(group.map(path => path[index]))); }, getElementClassSelectors(elements) { const classNameMap = new Map(); const classSelectors = []; for (let element of elements) { if (!element.classList.length) { classNameMap.clear(); break; } for (let className of Array.from(element.classList)) { classNameMap.set(className, (classNameMap.get(className) || 0) + 1); } } for (let [className, count] of classNameMap.entries()) { if (count === elements.length) { classSelectors.push('.' + escapeCSS(className)); } } return classSelectors; }, getElementIndices(elements) { return Array.from(new Set(elements.map(positionInParent))).sort((a, b) => a - b); }, generalizationDistance(element) { const paths = this.get('paths'); const groupedPaths = this.get('groupedPaths'); const newPath = elementPath(element); const newGroupedPaths = this.groupPaths([newPath].concat(paths)); if (newGroupedPaths.length > groupedPaths.length) { return Infinity; } const group = newGroupedPaths.find(group => group[0] === newPath); const pathLength = group[0].length; let distance = 0; let i = 0; const rejectElements = element => element === newPath[i]; for (i = 0; i < pathLength; i++) { const elements = this.getGroupElementsAtIndex(group, i); if (elements.length === 1) { continue; } const currentElements = elements.reject(rejectElements); const newClassSelectors = this.getElementClassSelectors(elements); const currentClassSelectors = this.getElementClassSelectors(currentElements); if (currentClassSelectors.length > newClassSelectors.length) { if (newClassSelectors.length >= 1 && (currentClassSelectors.length - newClassSelectors.length === 1)) { distance++; } else { return Infinity; } } const newIndices = this.getElementIndices(elements); const currentIndices = this.getElementIndices(currentElements); if (currentIndices.length < newIndices.length) { distance++; } } return distance; } }); export const AnnotationSelectorGenerator = BaseSelectorGenerator.extend({ selectorMatcher: null, annotation: null, acceptElements: computed('annotation.acceptSelectors.[]', function() { const acceptSelectors = this.get('annotation.acceptSelectors'); return this.get('selectorMatcher').query(this.mergeSelectors(acceptSelectors)); }), rejectElements: computed('annotation.rejectSelectors.[]', function() { const rejectSelectors = this.get('annotation.rejectSelectors'); return this.get('selectorMatcher').query(this.mergeSelectors(rejectSelectors)); }), generalizedSelector: computed( 'annotation.selectionMode', 'annotation.acceptSelectors.[]', 'acceptElements.[]', 'rejectElements.[]', function() { if (this.get('annotation.selectionMode') === 'css') { const acceptSelectors = this.get('annotation.acceptSelectors'); return this.mergeSelectors([acceptSelectors]); } const acceptElements = this.get('acceptElements'); const paths = acceptElements.map(elementPath); const groupedPaths = this.groupPaths(paths); const selectors = this.createGeneralizedSelectors(groupedPaths); return this.mergeSelectors(selectors); }), elements: computed('generalizedSelector', function() { const selector = this.get('generalizedSelector'); return this.get('selectorMatcher').query(selector); }), selector: computed( 'selectors', 'annotation.selectionMode', 'annotation.acceptSelectors.[]', 'acceptElements.[]', 'rejectElements.[]', function() { if (this.get('annotation.selectionMode') === 'css') { const acceptSelectors = this.get('annotation.acceptSelectors'); if (acceptSelectors.length === 1) { return this.mergeSelectors([acceptSelectors]); } const acceptElements = this.get('acceptElements'); const acceptPaths = acceptElements.map(elementPath); const acceptGroupedPaths = this.groupPaths(acceptPaths); const newAcceptSelectors = this.createSelectors(acceptGroupedPaths); return this.mergeSelectors(newAcceptSelectors); } const selectors = this.get('selectors'); const filteredSelectors = this.filterRejectedSelectors(selectors); return this.mergeSelectors(filteredSelectors); }), repeatedAnnotation: computed('selector', 'parent.repeatedContainers', function() { const parent = this.get('parent'); if (!parent) { return false; } const selector = this.get('selector'); const repeatedContainers = parent.get('repeatedContainers'); const selectorMatcher = this.get('selectorMatcher'); const elements = selectorMatcher.query(selector); if (!(selector && elements && elements.length > 1)) { return false; } if (repeatedContainers.length > 1) { for (let container of repeatedContainers) { let i = 0; for (let child of elements) { if (container.contains(child)) { i += 1; } if (i > 1) { break; } } if (i > 1) { return true; } } } const container = findContainers(elements)[0]; if (container) { const otherAnnotations = parent.get('children').filter(s => s !== parent); return !otherAnnotations.any(a => a.get('parent.container') === container); } return false; }), createGeneralizedSelectors(groupedPaths) { const selectors = groupedPaths.map(group => this.createGroupSelectors(group, null, true)); return this.filterRejectedSelectors(selectors); }, filterRejectedSelectors(selectors) { const selectorMatcher = this.get('selectorMatcher'); const rejectElements = new Set(this.get('rejectElements')); return selectors.map(selectors => { // if the generalized selector contains a rejected element, create a new selector // that matches only the other elements const elements = Array.from(selectorMatcher.query(this.mergeSelectors(selectors))); const allowedElements = elements.filter(element => !rejectElements.has(element)); if (elements.length === allowedElements.length) { return selectors; } const paths = allowedElements.map(elementPath); const allowedSelectors = this.createSelectors([paths]); return allowedSelectors[0]; }); } }); export const ContainerSelectorGenerator = BaseSelectorGenerator.extend({ init() { this._super(...arguments); this.set('children', []); }, destroy() { for (let child of this.get('children')) { child.set('parent', null); } this.set('children', null); this._super(...arguments); }, autoChildren: computed.filterBy('children', 'annotation.selectionMode', 'auto'), childElements: computed.mapBy('autoChildren', 'elements'), container: computed('childElements', function() { const childElements = this.get('childElements'); return findContainer(childElements); }), containerSelector: computed('container', function() { const container = this.get('container'); if (container) { const selectors = this.createSelectors([[elementPath(container)]]); return this.mergeSelectors(selectors); } return 'body'; }), repeatedContainersAndSiblings: computed('childElements', 'container', function() { const childElements = this.get('childElements'); const container = this.get('container'); // TODO: support separated trees return findRepeatedContainers(childElements, container); }), repeatedContainers: computed.readOnly('repeatedContainersAndSiblings.firstObject'), siblings: computed.readOnly('repeatedContainersAndSiblings.lastObject'), elements: computed('container', 'repeatedContainers', function() { const container = this.get('container'); const repeatedContainers = this.get('repeatedContainers'); if (repeatedContainers.length) { return repeatedContainers; } if (container) { return [container]; } return []; }), addChild(childGenerator) { this.get('children').addObject(childGenerator); childGenerator.set('parent', this); }, addChildren(childGenerators) { const children = this.get('children'); children.addObjects(childGenerators); for (let childGenerator of childGenerators) { childGenerator.set('parent', this); } } }); export function setIntersection(a, b) { return new Set([...a].filter(x => b.has(x))); } export function setDifference(a, b) { return new Set([...a].filter(x => !b.has(x))); } export function getParents(element, upto) { if (!element) { return []; } var parents = [], parent = element.parentElement; while (parent) { parents.push(parent); parent = parent.parentElement; if (parent === upto) { return parents; } } return parents; } export function getPreviousSiblings(element, upto) { if (!element) { return []; } var siblings = [], sibling = element.previousElementSibling; while (sibling && sibling !== upto) { siblings.push(sibling); sibling = sibling.previousElementSibling; } return siblings; } export function closestParentIndex(element, parents) { if (parents === undefined) { parents = getParents(element); parents.unshift(element); } let elementIndex = parents.indexOf(element); if (elementIndex < 0) { return 0; } return parents.length - elementIndex; } export function findContainers(extractedElements, upto) { let parentArrays = []; for (let element of extractedElements) { parentArrays.push(getParents(element, upto)); } let parentSets = parentArrays.map((array) => new Set(array)), intersection = parentSets[0] || new Set(); for (let set of parentSets.slice(1, parentSets.length)) { intersection = setIntersection(intersection, set); } return Array.from(intersection); } export function findContainer(extractedElements) { return findContainers([].concat(...extractedElements))[0]; } export function findRepeatedContainers(extracted, container) { let groupedItems = groupItems(extracted, container); if (groupedItems.length === 1) { return [[], 0]; } let repeatedParents = groupedItems.map((item) => findContainers(item, container)); if (repeatedParents.length === 0) { return [[], 0]; } let allEqualLength = repeatedParents.isEvery('length', repeatedParents[0].length); if (allEqualLength && new Set(repeatedParents.map((item) => item[0])).size === repeatedParents.length) { return [repeatedParents[0].length ? repeatedParents.map(list => list[0]) : [], 0]; } else { let shortest = Math.min(...repeatedParents.map(e => e.length)); repeatedParents = repeatedParents.map( (item) => item.slice(item.length - shortest, item.length)); if (new Set(repeatedParents.map((item) => item[0])).size === repeatedParents.length) { return [repeatedParents[0].length ? repeatedParents.map(list => list[0]) : [], 0]; } } return parentWithSiblings(groupedItems, container); } export function parentWithSiblings(groupedItems, container) { // 1. Get bounds let itemBounds = getItemBounds(groupedItems, false), itemParents = [], sharedItemParents = new Set(), sharedParents = new Set(); // 2. Using highest and lowest parents remove any parents shared by other groups for (let [highest, lowest] of itemBounds) { itemParents.push([getParents(highest, container).reverse(), getParents(lowest, container).reverse()]); } for (let fields of itemParents) { for (let fieldParents of fields) { for (let parent of fieldParents) { if (sharedItemParents.has(parent)) { sharedParents.add(parent); } else { sharedItemParents.add(parent); } } } } let i = 0; const filterNotShared = e => !sharedParents.has(e); for (let [highest, lowest] of itemParents) { itemParents[i] = [highest.filter(filterNotShared), lowest.filter(filterNotShared)]; i += 1; } // TODO: Check if not siblings // 3. For each item find sibling distance between highest and lowest if they // don't have a parent that isn't shared with other items. Use minimum let siblings = itemParents.map( (bounds) => getPreviousSiblings(bounds[1][0], bounds[0][0]).length + 1), siblingDistance = Math.min(...siblings); // 5. Use the highest unshared parent of the highest field of the first item // as the repeating container const containers = itemParents.map(lists => lists[0][0]) // remove undefined .filter(containers => !!containers); return [containers, siblingDistance]; } function getItemBounds(items, tagNumber=true) { let elementMap = {}; return items.map(function(elements) { let tagids = []; for (let element of elements) { // TODO: Find incrementing id from dom nodes rather than // attribute added by backend let tagid = element.getAttribute('data-tagid'); if (tagid) { tagid = parseInt(tagid); tagids.push(tagid); elementMap[tagid] = element; } } if (tagNumber) { return [Math.min(...tagids), Math.max(...tagids)]; } return [elementMap[Math.min(...tagids)], elementMap[Math.max(...tagids)]]; }); } export function groupItems(extracted, upto) { let groups = {}, id = 0; // Group fields based on their color // TODO: Group by schema too for (let elements of extracted) { groups[id] = elements; id += 1; } // If all groups are the same length page has a regular structure where // all items have the necessary fields and share a common repeating parent let groupLengths = new Set(Object.keys(groups).map((key) => groups[key].length)); if (groupLengths.size === 1) { return makeItemsFromGroups(groups); } let longest = Math.max(...groupLengths), longestGroups = {}, otherGroups = {}; for (let key in groups) { if (groups[key].length === longest) { longestGroups[key] = groups[key]; } else { otherGroups[key] = groups[key]; } } // Find bounding tagids for each item let items = makeItemsFromGroups(longestGroups), itemBounds = getItemBounds(items); let remainingFields = {}; let i = 0, seenElements = new Set(); // Place bounded elements into corresponding items and // find parents for unbounded fields for (let fieldKey in otherGroups) { let fieldGroup = otherGroups[fieldKey]; for (let element of fieldGroup) { i = 0; for (let [min, max] of itemBounds) { let tagid = parseInt(element.getAttribute('data-tagid')); if (tagid && tagid > min && tagid < max) { items[i].push(element); seenElements.add(element); break; } i += 1; } if (!seenElements.has(element)) { if (remainingFields[fieldKey]) { remainingFields[fieldKey].push([element, getParents(element, upto)]); } else { remainingFields[fieldKey] = [[element, getParents(element, upto)]]; } } } } // Find parents for each field in an item for all items let itemsParents = []; for (let item of items) { let itemParents = []; for (let element of item) { itemParents = itemParents.concat(getParents(element, upto)); } let parentCount = [], seenParents = [], orderedParents = []; for (let parent of itemParents) { let parentIdx = seenParents.indexOf(parent); if (parentIdx > 0) { parentCount[parentIdx] += 1; } else { parentCount.push(1); seenParents.push(parent); } } // Order parents by ones with the most descendant fields for (i=0; i < seenParents.length; i++) { orderedParents.push([parentCount[i], seenParents[i]]); } itemParents = []; for (let parent of orderedParents.sort()) { itemParents.push(parent[1]); } itemsParents.push(new Set(itemParents)); } // Remove parents shared by multiple items let uniqueParents = []; for (let parents of itemsParents) { for (let otherParents of itemsParents) { if (otherParents === parents) { continue; } parents = setDifference(parents, otherParents); } uniqueParents.push(parents); } i = 0; for (let itemParents of uniqueParents) { for (let key in remainingFields) { for (let [element, elementParents] of remainingFields[key]) { for (let parent of elementParents) { if (itemParents.has(parent)) { items[i].push(element); break; } } } } i += 1; } // TODO: Fields that are not in all items and are below the item bounds still // need to be matched -> all tests pass without this, need a breaking test return items; } export function makeItemsFromGroups(groups) { let items = []; for (let key of Object.keys(groups)) { for (let [i, item] of groups[key].entries()) { if (!items[i]) { items[i] = []; } items[i].push(item); } } return items; } export function createSelectorGenerators(structure, selectorMatcher) { const accumulator = []; accumulateSelectorGenerators(structure, selectorMatcher, accumulator); return accumulator; } function accumulateSelectorGenerators(structure, selectorMatcher, accumulator) { const generators = []; for (let element of structure) { const {annotation, children} = element; let selectorGenerator; if (children) { selectorGenerator = ContainerSelectorGenerator.create({}); selectorGenerator.addChildren( accumulateSelectorGenerators(children, selectorMatcher, accumulator)); } else { selectorGenerator = AnnotationSelectorGenerator.create({ selectorMatcher, annotation }); } generators.push(selectorGenerator); accumulator.push([annotation, selectorGenerator]); } return generators; } export default { BaseSelectorGenerator, AnnotationSelectorGenerator, ContainerSelectorGenerator, pathSelector, uniquePathSelector, smartSelector, cssToXpath, findContainer, findRepeatedContainers }; ================================================ FILE: portiaui/app/utils/start-urls.js ================================================ const SAMPLE_SIZE = 20; const ALL_DIGITS = /^\d+-\d+$/; const ALL_LETTERS = /^[a-zA-Z]+-[a-zA-Z]+$/; function nextLetter(letter) { return String.fromCharCode(letter.charCodeAt(0) + 1); } function numberRange(a, b) { const numbers = []; for(let i = a; i < b + 1; i += 1) { numbers.push(i.toString()); } return numbers; } function letterRange(a, b) { const letters = []; letters.push(a); while(!letters.contains(b)) { const lastLetter = letters.get('lastObject'); letters.pushObject(nextLetter(lastLetter)); } return letters; } function _processDigitRange(value) { const endpoints = value.split('-'); let [a, b] = endpoints.map(x => parseInt(x)); b = Math.min(b, a + SAMPLE_SIZE); return [a, b]; } function augmentRange(fragment_value) { if (allDigits(fragment_value)) { const [a, b] = _processDigitRange(fragment_value); return numberRange(a, b); } if (allLetters(fragment_value)) { const [a, b] = fragment_value.split('-'); return letterRange(a, b); } } function augmentFragment(fragment) { switch(fragment.type) { case('fixed'): return [fragment.value]; case('list'): return fragment.value.split(' '); case('range'): const value = fragment.value; if (allLetters(value) || allDigits(value)) { return augmentRange(value); } return ['']; } } export function allLetters(value) { return value.match(ALL_LETTERS); } export function allDigits(value) { return value.match(ALL_DIGITS); } export function fragmentToString(fragment) { switch(fragment.type) { case('fixed'): return fragment.value; case('list'): return '[...]'; case('range'): return '[' + fragment.value + ']'; } } export function augmentFragmentList(fragmentList, fragment) { const result = []; const newFragments = augmentFragment(fragment); newFragments.forEach((newFragment) => { result.push(fragmentList.concat(newFragment)); }); return result; } export function includesUrl(spider, url) { return spider.get('startUrls').mapBy('url').includes(url); } export function multiplicityFragment(fragment) { switch(fragment.type) { case('fixed'): return 1; case('list'): return fragment.value.split(' ').length; case('range'): const value = fragment.value; const [a, b] = value.split('-'); if (allLetters(value)) { return letterRange(a, b).length; } if (allDigits(value)) { return numberRange(parseInt(a), parseInt(b)).length; } return 1; } } export default { allDigits, allLetters, augmentFragmentList, fragmentToString, includesUrl, multiplicityFragment }; ================================================ FILE: portiaui/app/utils/tree-mirror-delegate.js ================================================ function paintCanvasMessage(canvas) { var ctx = canvas.getContext('2d'); var pattern = document.createElement('canvas'); pattern.width = 20; pattern.height = 20; var pctx = pattern.getContext('2d'); pctx.fillStyle = "#ccc"; pctx.fillRect(0,0,10,10); pctx.fillRect(10,10,10,10); pattern = ctx.createPattern(pattern, "repeat"); ctx.fillStyle = pattern; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.font = '16px sans-serif'; ctx.fillStyle = 'black'; ctx.fillText('Displaying the content of the canvas is not supported', 10, canvas.height / 2); } function addEmbedBlockedMessage(node) { if(!node || !node.parentNode || /EMBED|OBJECT/.test(node.parentNode.tagName)) { return; } var computedStyle = window.getComputedStyle(node); var width = node.hasAttribute("width")?node.getAttribute("width")+"px":computedStyle.width; var height = node.hasAttribute("height")?node.getAttribute("height")+"px":computedStyle.height; var errorMsg = $("
    ").css({ 'background-color': '#269', 'background-image': 'linear-gradient(rgba(255,255,255,.2) 1px, transparent 1px), ' + 'linear-gradient(90deg, rgba(255,255,255,.2) 1px, transparent 1px)', 'background-size': '20px 20px, 20px 20px', 'text-align': "center", 'overflow': "hidden", 'font-size': "18px", 'display': "block", 'font-family': 'sans-serif', 'color': 'white', 'text-shadow': '1px black', 'width': width, 'height': height, 'lineHeight': height, }).text("Portia doesn't support browser plugins."); node.style.display = "none"; node.parentNode.insertBefore(errorMsg[0], node); } export default function treeMirrorDelegate(){ return { cssEnabled: true, createElement: function(tagName) { var node = null; if(tagName === 'SCRIPT' || tagName === 'META' || tagName === 'BASE') { node = document.createElement('NOSCRIPT'); } else { try { node = document.createElement(tagName); } catch(e) { // Invalid tag name node = document.createElement('NOSCRIPT'); } } if(tagName === 'FORM') { $(node).on('submit', ()=>false); } else if (tagName === 'IFRAME' || tagName === 'FRAME') { node.setAttribute('src', '/static/frames-not-supported.html'); } else if (tagName === 'CANVAS') { paintCanvasMessage(node); } else if (tagName === 'OBJECT' || tagName === 'EMBED') { setTimeout(addEmbedBlockedMessage.bind(null, node), 100); } return node; }, setAttribute: function(node, attrName, value){ if( /^on/.test(attrName) || // Disallow JS attributes ((node.tagName === 'FRAME' || node.tagName === 'IFRAME') && (attrName === 'src' || attrName === 'srcdoc')) || // Frames not supported ((node.tagName === 'OBJECT' || node.tagName === 'EMBED') && (attrName === 'data' || attrName === 'src')) // Block embed / object ) { return true; } // make sure tree mutations take into account disabled CSS if (!this.cssEnabled) { if (attrName === 'style') { attrName = 'data-portia-hidden-style'; } else if (node.tagName === 'STYLE' && attrName === 'media') { attrName = 'data-portia-hidden-media'; } else if (node.tagName === 'LINK') { if (attrName === 'media' && node.getAttribute('rel') === 'stylesheet') { attrName = 'data-portia-hidden-media'; } else if (attrName === 'rel' && value === 'stylesheet' && node.hasAttribute('media')) { node.setAttribute('data-portia-hidden-media', node.getAttribute('media')); node.removeAttribute('media'); } } } try{ node.setAttribute(attrName, value); }catch(e){ console.log(e, attrName, value); } if(node.tagName === 'CANVAS' && (attrName === 'width' || attrName === 'height')) { paintCanvasMessage(node); } return true; } }; } ================================================ FILE: portiaui/app/utils/types.js ================================================ export function toType(obj) { return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } export function isObject(obj) { return toType(obj) === 'object'; } export function isArray(obj) { return Array.isArray(obj); } ================================================ FILE: portiaui/app/utils/utils.js ================================================ import Ember from 'ember'; /** * Cleans, normalizes and validates URLs */ export function cleanUrl(url) { if(typeof url !== 'string') { return null; } url = url.trim(); if(!/^https?:\/\//i.test(url)) { url = 'http://' + url; } try { url = (new URI(url)).normalize(); } catch(e){ return null; } if(!url.host()) { return null; } return url.toString(); } /** * Four random hex characters */ function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } export function guid() { return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); } export function shortGuid(separator='-') { return s4() + separator + s4() + separator + s4(); } export function toType(obj) { return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } export function captureMessage(msg, params) { Ember.Logger.log(msg); if (window.Raven) { Raven.captureMessage(msg, params); } } export function logError(err, params) { Ember.Logger.error(err); if (window.Raven) { Raven.captureException(err, params); } } export function renameAttr($elements, from, to) { if (to === from) { return $elements; } return $elements.each(function() { if (this.hasAttribute(from)) { this.setAttribute(to, this.getAttribute(from)); this.removeAttribute(from); } else if (this.hasAttribute(to)) { this.removeAttribute(to); } }); } export function flatten(list) { const result = []; list.forEach((element) => { element.forEach((nested) => { result.push(nested); }); }); return result; } ================================================ FILE: portiaui/app/validations/fixed-fragment.js ================================================ import { validatePresence } from 'ember-changeset-validations/validators'; import validateWhitespace from '../validators/whitespace'; export default { value: [ validatePresence({ presence: true, message: 'Should not be empty.'}), validateWhitespace() ] }; ================================================ FILE: portiaui/app/validations/list-fragment.js ================================================ import { validatePresence } from 'ember-changeset-validations/validators'; export default { value: validatePresence(true) }; ================================================ FILE: portiaui/app/validations/range-fragment.js ================================================ import validateRange from '../validators/range'; export default { value: validateRange() }; ================================================ FILE: portiaui/app/validators/range.js ================================================ import { allLetters, allDigits } from '../utils/start-urls'; function hasMixedCase(endpoints) { return endpoints.match(/[a-z]/) && endpoints.match(/[A-Z]/); } function hasSingleLetters(endpoints) { return endpoints.split('-').every((x) => x.length === 1); } function isRangeIncomplete(endpoints) { return endpoints.split('-').contains(''); } function validateIncreasing(endpoints, isIncreasing) { const [a, b] = endpoints.split('-'); const msg = `A range must be increasing. Try swapping to ${b}-${a}.`; return isIncreasing(a, b) || msg; } export default function validateRange() { return (key, newValue/*, oldValue, changes */) => { if (isRangeIncomplete(newValue)) { return 'A range must have both a start and an end.'; } if (allDigits(newValue)) { return validateIncreasing(newValue, (a, b) => parseInt(a) <= parseInt(b)); } if (allLetters(newValue)) { if (!hasSingleLetters(newValue)) { return 'A range must have only single letters.'; } if (hasMixedCase(newValue)) { return 'A range cannot mix lower and upper case.'; } return validateIncreasing(newValue, (a, b) => a <= b); } return 'A range must not mix numbers and letters.'; }; } ================================================ FILE: portiaui/app/validators/whitespace.js ================================================ export default function validateWhitespace() { return (key, newValue/*, oldValue, changes */) => { return newValue.match(/\s/g) ? 'Should not have whitespace' : true; }; } ================================================ FILE: portiaui/bower.json ================================================ { "name": "portia-ui", "ignore": [ "*", "!bower.json" ], "dependencies": { "ember": "~2.6.0", "ember-cli-shims": "0.1.1", "ember-cli-test-loader": "0.2.2", "ember-qunit-notifications": "0.1.0", "jquery": "^2.2.0", "blob-polyfill": "~1.0.20150320", "cookie": "~1.1.0", "bootstrap-sass": "~3.3.6", "font-awesome": "~4.5.0", "jquery-color": "~2.1.2", "moment": "~2.11.2", "uri.js": "~1.16.0", "fetch": "~0.10.1", "es6-promise": "~3.0.2", "uri-templates": "~0.1.9", "css-escape": "~1.5.0", "animation-frame": "~0.2.4" }, "private": true } ================================================ FILE: portiaui/config/deprecation-workflow.js ================================================ window.deprecationWorkflow = window.deprecationWorkflow || {}; window.deprecationWorkflow.config = { workflow: [ { handler: "silence", matchMessage: /You modified .+ twice in a single render. This was unreliable in Ember 1.x and will be removed in Ember 3.0/ } ] }; ================================================ FILE: portiaui/config/environment-development.js ================================================ /* jshint node: true */ module.exports = function(ENV) { ENV.APP.LOG_ACTIVE_GENERATION = true; ENV.APP.LOG_TRANSITIONS = true; ENV.APP.LOG_TRANSITIONS_INTERNAL = true; ENV.APP.LOG_VIEW_LOOKUPS = true; //ENV.APP.LOG_RESOLVER = true; return ENV; }; ================================================ FILE: portiaui/config/environment-production.js ================================================ /* jshint node: true */ module.exports = function(ENV) { return ENV; }; ================================================ FILE: portiaui/config/environment-test.js ================================================ /* jshint node: true */ module.exports = function(ENV) { // Testem prefers this... ENV.baseURL = '/'; ENV.locationType = 'none'; // keep test console output quieter ENV.APP.LOG_ACTIVE_GENERATION = false; ENV.APP.LOG_VIEW_LOOKUPS = false; ENV.APP.rootElement = '#ember-testing'; return ENV; }; ================================================ FILE: portiaui/config/environment.js ================================================ /* jshint node: true */ var path = require('path'), envModule; module.exports = function(environment) { var ENV = { modulePrefix: 'portia-ui', environment: environment, baseURL: '/', locationType: 'hash', contentSecurityPolicy: { 'default-src': "'none'", 'script-src': "* 'unsafe-inline' 'unsafe-eval'", 'style-src': "* 'unsafe-inline'", 'img-src': "* data:", 'connect-src': "*", 'font-src': "*", 'object-src': "*", 'media-src': "*", 'frame-src': "'none'" }, EmberENV: { FEATURES: { // Here you can enable experimental features on an ember canary build // e.g. 'with-controller': true } }, APP: { // Here you can pass flags/options to your application instance // when it is created allow_nesting: true } }; try { envModule = require(path.join(process.cwd(), 'config/environment-' + environment)); } catch (e) { console.log('Config module for "' + environment + '" not found.'); } if (typeof envModule === 'function') { ENV = envModule(ENV); } return ENV; }; ================================================ FILE: portiaui/ember-cli-build.js ================================================ /* global require, module */ var EmberApp = require('ember-cli/lib/broccoli/ember-app'); var UnwatchedDir = require('broccoli-source').UnwatchedDir; var WatchedDir = require('broccoli-source').WatchedDir; var concat = require('broccoli-concat'); var mergeTrees = require('ember-cli/lib/broccoli/merge-trees'); module.exports = function(defaults) { var app = new EmberApp(defaults, { babel: { includePolyfill: true } }); app.import('bower_components/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js'); app.import('bower_components/cookie/cookie.min.js'); app.import('bower_components/jquery-color/jquery.color.js'); app.import('bower_components/moment/min/moment.min.js'); app.import('bower_components/uri.js/src/URI.min.js'); app.import('bower_components/css-escape/css.escape.js'); app.import('vendor/tree-mirror.js'); app.import('vendor/modernizr.js'); ['eot', 'svg', 'ttf', 'woff', 'woff2'].forEach(function(file) { app.import('bower_components/font-awesome/fonts/fontawesome-webfont.' + file, { destDir: 'assets/fonts' }); }); // Splash scripts var splashTree = concat(mergeTrees([ new WatchedDir(app._resolveLocal('../splash_utils')), new UnwatchedDir(app._resolveLocal('vendor')) ], { annotation: 'TreeMerger (splash utils)' }), { inputFiles: [ 'mutation-summary.js', 'tree-mirror.js', // LocalStorage Shim disabled since it doesn't work in Qt5 // 'local-storage-shim.js', 'z_inject_this.js' ], outputFile: 'splash_content_scripts/combined.js', header: '(function(){', footer: '})();' }); return mergeTrees([ app.toTree(), splashTree ]); }; ================================================ FILE: portiaui/package.json ================================================ { "name": "portia-ui", "version": "2.0.0-alpha", "description": "User interface for the Portia visual scraping tool", "private": true, "directories": { "doc": "doc", "test": "tests" }, "scripts": { "build": "bower install && ember build -e production", "start": "ember server", "test": "ember test" }, "engines": { "node": ">= 0.10.0" }, "author": "", "license": "MIT", "devDependencies": { "bower": "^1.8.4", "broccoli-asset-rev": "^2.4.2", "broccoli-concat": "^3.2.2", "broccoli-source": "^1.1.0", "ember-ajax": "^2.0.1", "ember-api-actions": "0.0.11", "ember-api-requests": "0.3.0", "ember-changeset": "1.1.2", "ember-changeset-validations": "1.2.0", "ember-cli": "2.6.3", "ember-cli-app-version": "^1.0.0", "ember-cli-autoprefixer": "^0.6.0", "ember-cli-babel": "^6.6.0", "ember-cli-content-security-policy": "0.5.0", "ember-cli-dependency-checker": "^1.2.0", "ember-cli-deprecation-workflow": "^0.2.3", "ember-cli-htmlbars": "^1.0.3", "ember-cli-htmlbars-inline-precompile": "^1.0.3", "ember-cli-inject-live-reload": "^1.4.0", "ember-cli-jshint": "^1.0.0", "ember-cli-loading-slider": "^1.3.0", "ember-cli-qunit": "^1.4.0", "ember-cli-release": "^0.2.9", "ember-cli-sass": "^7.2.0", "ember-cli-sri": "^2.1.0", "ember-cli-uglify": "^1.2.0", "ember-concurrency": "0.7.10", "ember-data": "~2.11.3", "ember-data-url-templates": "0.1.1", "ember-export-application-global": "^1.0.5", "ember-load-initializers": "^0.5.1", "ember-local-storage": "^1.3.0", "ember-resolver": "^2.0.3", "ember-route-action-helper": "0.3.1", "ember-run-raf": "1.1.2", "ember-truth-helpers": "^1.2.0", "loader.js": "^4.0.1" } } ================================================ FILE: portiaui/public/crossdomain.xml ================================================ ================================================ FILE: portiaui/public/empty-frame.html ================================================ ================================================ FILE: portiaui/public/frames-not-supported.html ================================================

    :(
    Frames are not supported by Portia

    ================================================ FILE: portiaui/public/robots.txt ================================================ # http://www.robotstxt.org User-agent: * Disallow: ================================================ FILE: portiaui/testem.js ================================================ /*jshint node:true*/ module.exports = { "framework": "qunit", "test_page": "tests/index.html?hidepassed", "disable_watching": true, "launch_in_ci": [ "PhantomJS" ], "launch_in_dev": [ "PhantomJS", "Chrome" ] }; ================================================ FILE: portiaui/tests/.jshintrc ================================================ { "predef": [ "document", "window", "location", "setTimeout", "$", "-Promise", "define", "console", "visit", "exists", "fillIn", "click", "keyEvent", "triggerEvent", "find", "findWithAssert", "wait", "DS", "andThen", "currentURL", "currentPath", "currentRouteName" ], "node": false, "browser": false, "boss": true, "curly": true, "debug": false, "devel": false, "eqeqeq": true, "evil": true, "forin": false, "immed": false, "laxbreak": false, "newcap": true, "noarg": true, "noempty": false, "nonew": false, "nomen": false, "onevar": false, "plusplus": false, "regexp": false, "undef": true, "sub": true, "strict": false, "white": false, "eqnull": true, "esnext": true, "unused": true } ================================================ FILE: portiaui/tests/helpers/destroy-app.js ================================================ import Ember from 'ember'; export default function destroyApp(application) { Ember.run(application, 'destroy'); } ================================================ FILE: portiaui/tests/helpers/module-for-acceptance.js ================================================ import { module } from 'qunit'; import Ember from 'ember'; import startApp from '../helpers/start-app'; import destroyApp from '../helpers/destroy-app'; const { RSVP: { Promise } } = Ember; export default function(name, options = {}) { module(name, { beforeEach() { this.application = startApp(); if (options.beforeEach) { return options.beforeEach.apply(this, arguments); } }, afterEach() { let afterEach = options.afterEach && options.afterEach.apply(this, arguments); return Promise.resolve(afterEach).then(() => destroyApp(this.application)); } }); } ================================================ FILE: portiaui/tests/helpers/resolver.js ================================================ import Resolver from '../../resolver'; import config from '../../config/environment'; const resolver = Resolver.create(); resolver.namespace = { modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix }; export default resolver; ================================================ FILE: portiaui/tests/helpers/start-app.js ================================================ import Ember from 'ember'; import Application from '../../app'; import config from '../../config/environment'; export default function startApp(attrs) { let application; let attributes = Ember.merge({}, config.APP); attributes = Ember.merge(attributes, attrs); // use defaults, but you can override; Ember.run(() => { application = Application.create(attributes); application.setupForTesting(); application.injectTestHelpers(); }); return application; } ================================================ FILE: portiaui/tests/index.html ================================================ PortiaWeb Tests {{content-for "head"}} {{content-for "test-head"}} {{content-for "head-footer"}} {{content-for "test-head-footer"}} {{content-for "body"}} {{content-for "test-body"}} {{content-for "body-footer"}} {{content-for "test-body-footer"}} ================================================ FILE: portiaui/tests/test-helper.js ================================================ import resolver from './helpers/resolver'; import { setResolver } from 'ember-qunit'; setResolver(resolver); ================================================ FILE: portiaui/tests/unit/.gitkeep ================================================ ================================================ FILE: portiaui/tests/unit/models/start-url-test.js ================================================ import buildStartUrl from '../../../models/start-url'; import { moduleForModel, test } from 'ember-qunit'; moduleForModel('start-url', 'Unit | Model | start-url', { needs: [] }); test('it generates a correct url list', function(assert) { const urlString = 'http://domain.com'; const url = buildStartUrl({ type: 'generated', url: urlString}); assert.deepEqual(url.generateList(), [[urlString]]); }); test('it generates a list with a list fragment', function(assert) { const urlString = 'http://domain.com'; const url = buildStartUrl({ type: 'generated', url: urlString}); url.fragments.addObject({type: 'list', value: 'a b'}); const result = [ [urlString, 'a'], [urlString, 'b'] ]; assert.deepEqual(url.generateList(), result); }); test('it generates a list with a range fragment', function(assert) { const urlString = 'http://domain.com'; const url = buildStartUrl({ type: 'generated', url: urlString}); url.fragments.addObject({type: 'range', value: '0-2'}); const result = [ [urlString, '0'], [urlString, '1'], [urlString, '2'] ]; assert.deepEqual(url.generateList(), result); }); test('it generates a list with a letter range fragment', function(assert) { const urlString = 'http://domain.com'; const url = buildStartUrl({ type: 'generated', url: urlString}); url.fragments.addObject({type: 'range', value: 'a-c'}); const result = [ [urlString, 'a'], [urlString, 'b'], [urlString, 'c'] ]; assert.deepEqual(url.generateList(), result); }); test('it generates a combined fragment correctly', function(assert) { const urlString = 'http://domain.com'; const url = buildStartUrl({ type: 'generated', url: urlString}); url.fragments.addObject({type: 'list', value: 'a b'}); url.fragments.addObject({type: 'range', value: '0-1'}); url.fragments.addObject({type: 'fixed', value: '/ending'}); const result = [ [urlString, 'a', '0', '/ending'], [urlString, 'a', '1', '/ending'], [urlString, 'b', '0', '/ending'], [urlString, 'b', '1', '/ending'] ]; assert.deepEqual(url.generateList(), result); }); test('it treats ranges nicely', function(assert) { const urlString = 'http://domain.com'; const url = buildStartUrl({ type: 'generated', url: urlString}); url.fragments.addObject({type: 'range', value: '0-'}); const result = [ [urlString, ''] ]; assert.deepEqual(url.generateList(), result); }); function assertFeedsEqual(assert, url, test_url) { const feed = buildStartUrl({ type: 'feed', url: url}); assert.equal(feed.show(), test_url); } test('it rawifies a github nonraw gist', function(assert) { assertFeedsEqual( assert, 'https://gist.github.com/user/gist_id', 'https://gist.github.com/user/gist_id/raw' ); }); test('it rawifies a github nonraw trailing gist', function(assert) { assertFeedsEqual( assert, 'https://gist.github.com/user/gist_id/', 'https://gist.github.com/user/gist_id/raw' ); }); test('it does nothing with a github raw gist', function(assert) { const gistUrl = 'https://gist.github.com/user/gist_id/raw'; assertFeedsEqual(assert, gistUrl, gistUrl); }); test('it rawifies a dropbox shareable link', function(assert) { assertFeedsEqual( assert, 'https://www.dropbox.com/s/dropbox-id/urls.txt?dl=0', 'https://www.dropbox.com/s/dropbox-id/urls.txt?dl=0&raw=1' ); }); test('it rawifies a google shareable link', function(assert) { assertFeedsEqual( assert, 'https://docs.google.com/document/d/drive-id/edit?usp=sharing', 'https://docs.google.com/document/d/drive-id/export?format=txt' ); }); test('it does not rawify a non drive google link', function(assert) { assertFeedsEqual( assert, 'http://google.com/sitemap.xml', 'http://google.com/sitemap.xml' ); }); ================================================ FILE: portiaui/tests/unit/utils/selectors-test.js ================================================ import Ember from 'ember'; import SelectorMatcher from '../../../services/selector-matcher'; import { findContainer, findRepeatedContainers, BaseSelectorGenerator, ContainerSelectorGenerator, AnnotationSelectorGenerator } from '../../../utils/selectors'; import { module, test, skip } from 'qunit'; module('Unit | Utility | selectors'); class MockBrowser { constructor(documentRoot) { this.$document = Ember.$(documentRoot); } } test('BaseSelectorGenerator computes paths for all elements', function(assert) { const $elements = Ember.$('
    '); const selector = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#div2, #li1, #li2, #li3').toArray() }); const idPaths = selector.get('paths').map( path => path.map( element => element.id)); assert.deepEqual(idPaths, [ ['main', 'div1', 'div2'], ['main', 'div1', 'ul1', 'li1'], ['main', 'div1', 'ul1', 'li2'], ['main', 'div1', 'ul1', 'li3'] ]); }); test('BaseSelectorGenerator groups paths for all elements', function(assert) { const $elements = Ember.$('
    '); const selector = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#div2, #li1, #li2, #li3').toArray() }); const groupedIdPaths = selector.get('groupedPaths').map( group => group.map( path => path.map( element => element.id))); assert.deepEqual(groupedIdPaths, [ [ ['main', 'div1', 'div2'] ], [ ['main', 'div1', 'ul1', 'li1'], ['main', 'div1', 'ul1', 'li2'], ['main', 'div1', 'ul1', 'li3'] ] ]); }); test('BaseSelectorGenerator generates selectors for groups of elements', function(assert) { const $elements = Ember.$('
    '); const selector = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#div2, #li1, #li2, #li3').toArray() }); assert.deepEqual(selector.get('selectors'), [ ['#div2'], ['li'] ]); assert.equal(selector.get('selector'), '#div2, li'); }); test('BaseSelectorGenerator nesting generates correct selectors', function(assert) { const $elements = Ember.$('
    '); const selectorParent = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#div1, #li1, #li2, #li3').toArray() }); const selector = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), parent: selectorParent, elements: $elements.find('#div2, #li1').toArray() }); assert.deepEqual(selector.get('selectors'), [ ['#div1 > div'], ['li'] ]); assert.equal(selector.get('selector'), '#div1 > div, li'); }); test('ContainerSelectorGenerator propagates groups to child selectors', function(assert) { const $elements = Ember.$('
      ' + '
    • ' + '
    • ' + '
    • ' + '
    '); const selectorParent = ContainerSelectorGenerator.create({}); const selector1 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span1-1').toArray() }); const selector2 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span1-2, #span2-2, #span3-2').toArray() }); const selector3 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span1-3').toArray() }); selectorParent.addChildren([selector1, selector2, selector3]); assert.equal(selector1.get('selector'), 'li > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li > span:nth-child(3)'); }); test('ContainerSelectorGenerator propagates groups to disjoint child selectors', function(assert) { const $elements = Ember.$('
      ' + '
    • ' + '
    • ' + '
    • ' + '
    '); const selectorParent = ContainerSelectorGenerator.create({}); const selector1 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span1-1').toArray() }); const selector2 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span1-2, #span2-2, #span3-2').toArray() }); const selector3 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span2-3').toArray() }); selectorParent.addChildren([selector1, selector2, selector3]); assert.equal(selector1.get('selector'), 'li > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li > span:nth-child(3)'); }); skip('ContainerSelectorGenerator propagates groups to child selectors with additional trees', function(assert) { const $elements = Ember.$('
      ' + '
    • ' + '
    • ' + '
    • ' + '
    '); const selectorParent = ContainerSelectorGenerator.create({}); const selector1 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#div2, #span1-1').toArray() }); const selector2 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span1-2, #span2-2, #span3-2').toArray() }); const selector3 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span2-3').toArray() }); selectorParent.addChildren([selector1, selector2, selector3]); assert.equal(selector1.get('selector'), '#div2, li > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li > span:nth-child(3)'); }); test('ContainerSelectorGenerator propagates changes in a child selector to other children', function(assert) { const $elements = Ember.$('
      ' + '
    • ' + '
    • ' + '
    • ' + '
    '); const selectorParent = ContainerSelectorGenerator.create({}); const selector1 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span1-1').toArray() }); const selector2 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span1-2, #span2-2').toArray() }); const selector3 = BaseSelectorGenerator.create({ annotation: Ember.Object.create({selectionMode: 'auto'}), elements: $elements.find('#span2-3').toArray() }); selectorParent.addChildren([selector1, selector2, selector3]); assert.equal(selector1.get('selector'), 'li:nth-child(-n+2) > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li:nth-child(-n+2) > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li:nth-child(-n+2) > span:nth-child(3)'); selector2.set('elements', $elements.find('#span1-2, #span2-2, #span3-2').toArray()); assert.equal(selector1.get('selector'), 'li > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li > span:nth-child(3)'); }); test('AnnotationSelectorGenerator generates selectors for groups of elements', function(assert) { const $elements = Ember.$('
    '); const selectorMatcher = SelectorMatcher.create({ browser: new MockBrowser($elements) }); const selector = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ selectionMode: 'auto', acceptSelectors: ["#div2", "#li1", "#li2", "#li3"], rejectSelectors: [] }) }); assert.equal(selector.get('generalizedSelector'), '#div2, #ul1 > li'); assert.deepEqual(selector.get('selectors'), [ ['#div2'], ['li'] ]); assert.equal(selector.get('selector'), '#div2, li'); }); test('AnnotationSelectorGenerator generates generalized selectors', function(assert) { const $elements = Ember.$('
    '); const selectorMatcher = SelectorMatcher.create({ browser: new MockBrowser($elements) }); const selector2 = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ selectionMode: 'auto', acceptSelectors: ["#div2", "#li1", "#li2"], rejectSelectors: [] }) }); assert.equal(selector2.get('generalizedSelector'), '#div2, #ul1 > li'); assert.equal(selector2.get('selector'), '#div2, li'); }); test('AnnotationSelectorGenerator generates repeated selectors for repeated field', function(assert) { const $elements = Ember.$('
    '); const selectorMatcher = SelectorMatcher.create({ browser: new MockBrowser($elements) }); const selectorParent = ContainerSelectorGenerator.create({}); const repeatedSelector = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ selectionMode: 'auto', acceptSelectors: ["#li1", "#li2"], rejectSelectors: [] }) }); const standardSelector = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ selectionMode: 'auto', acceptSelectors: ["#div2"], rejectSelectors: [] }) }); selectorParent.addChildren([standardSelector, repeatedSelector]); assert.equal(repeatedSelector.get('generalizedSelector'), '#ul1 > li'); assert.equal(repeatedSelector.get('repeatedAnnotation'), true); assert.equal(repeatedSelector.get('selector'), '#div1 > ul > li'); assert.equal(standardSelector.get('generalizedSelector'), '#div2'); assert.equal(standardSelector.get('repeatedAnnotation'), false); assert.equal(standardSelector.get('selector'), '#div1 > div'); assert.equal(selectorParent.get('containerSelector'), '#div1'); assert.equal(selectorParent.get('selector'), '#div1'); }); test('AnnotationSelectorGenerator supports rejecting selectors', function(assert) { const $elements = Ember.$('
    '); const selectorMatcher = SelectorMatcher.create({ browser: new MockBrowser($elements) }); const selector = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ selectionMode: 'auto', acceptSelectors: ["#div2", "#li1", "#li2"], rejectSelectors: ["#li3"] }) }); assert.equal(selector.get('generalizedSelector'), '#div2, li:nth-child(-n+2)'); assert.equal(selector.get('selector'), '#div2, li:nth-child(-n+2)'); }); test('AnnotationSelectorGenerator changes get propagated to siblings', function(assert) { const $elements = Ember.$('
      ' + '
    • ' + '
    • ' + '
    • ' + '
    '); const selectorMatcher = SelectorMatcher.create({ browser: new MockBrowser($elements) }); const selectorParent = ContainerSelectorGenerator.create({}); const selector1 = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ id: 1, selectionMode: 'auto', acceptSelectors: ['#span1-1'], rejectSelectors: [] }) }); const selector2 = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ id: 2, selectionMode: 'auto', acceptSelectors: ['#span1-2'], rejectSelectors: [] }) }); const selector3 = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ id: 3, selectionMode: 'auto', acceptSelectors: ['#span2-3'], rejectSelectors: [] }) }); selectorParent.addChildren([selector1, selector2, selector3]); assert.equal(selector1.get('selector'), '#ul1 > li:nth-child(1) > span:nth-child(1)'); assert.equal(selector2.get('selector'), '#ul1 > li:nth-child(1) > span:nth-child(2)'); assert.equal(selector3.get('selector'), '#ul1 > li:nth-child(2) > span:nth-child(3)'); selector2.get('annotation.acceptSelectors').pushObject('#span2-2'); assert.equal(selector1.get('selector'), 'li > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li > span:nth-child(3)'); selector2.get('annotation.rejectSelectors').pushObject('#span3-2'); assert.equal(selector1.get('selector'), 'li:nth-child(-n+2) > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li:nth-child(-n+2) > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li:nth-child(-n+2) > span:nth-child(3)'); }); test('Nested AnnotationSelectorGenerator supports rejecting elements', function(assert) { const $elements = Ember.$('
      ' + '
    • ' + '
    • ' + '
    • ' + '
    '); const selectorMatcher = SelectorMatcher.create({ browser: new MockBrowser($elements) }); const selectorParent = ContainerSelectorGenerator.create({}); const selector1 = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ id: 1, selectionMode: 'auto', acceptSelectors: ['#span1-1'], rejectSelectors: [] }) }); const selector2 = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ id: 2, selectionMode: 'auto', acceptSelectors: ['#span1-2', '#span2-2', '#span3-2'], rejectSelectors: [] }) }); const selector3 = AnnotationSelectorGenerator.create({ selectorMatcher, annotation: Ember.Object.create({ id: 3, selectionMode: 'auto', acceptSelectors: ['#span2-3'], rejectSelectors: [] }) }); selectorParent.addChildren([selector1, selector2, selector3]); assert.equal(selector1.get('selector'), 'li > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li > span:nth-child(3)'); selector3.get('annotation.rejectSelectors').pushObject('#span1-3'); assert.equal(selector1.get('selector'), 'li > span:nth-child(1)'); assert.equal(selector2.get('selector'), 'li > span:nth-child(2)'); assert.equal(selector3.get('selector'), 'li:nth-child(n+2) > span:nth-child(3)'); }); var commonFields = 'image title address area description price'.split(' '); var getElements = function(testCase, fields) { let selectors = { image: `${testCase} .image > img`, title: `${testCase} .title > h3`, address: `${testCase} .address`, area: `${testCase} .address > span:nth-child(2)`, description: `${testCase} .description > p`, price: `${testCase} .description > span`, view: `${testCase} .views > span:nth-child(2)`, info: `${testCase} .info > span:nth-child(2)` }; let structure = []; for (let field of fields) { structure.push(Array.from(doc.querySelectorAll(selectors[field]))); } return structure; }; var runTest = function(assert, type, fields, expected) { let elements = getElements(type, fields), container = findContainer(elements), [repeatedContainers, siblings] = findRepeatedContainers(elements, container); let containerId = '0'; if (container) { containerId = container.getAttribute('data-tagid'); } let repeatedContainerIds = repeatedContainers.map( element => element.getAttribute('data-tagid')); assert.deepEqual([containerId, repeatedContainerIds, siblings], expected); }; test('regular', function(assert) { runTest(assert, '#regular-structure', commonFields, [ '5', [ '6', '17', '28', '39', '50', '61', '72', '83', '94' ], 0 ]); }); test('regular-with-unneeded-rows', function(assert) { runTest(assert, '#regular-with-unneeded-rows', commonFields, [ '107', [ '108', '121', '134', '147', '160', '173', '186', '199', '212' ], 0 ]); }); test('nested-rows-and-columns', function(assert) { runTest(assert, '#nested-rows-and-columns', commonFields, [ '225', [ '227', '238', '249', '261', '272', '283', '295', '306', '317' ], 0 ]); }); test('items-with-some-fields-missing', function(assert) { runTest(assert, '#items-with-some-fields-missing', commonFields, [ '330', [ '331', '339', '350', '361', '372', '383', '391', '402', '410' ], 0 ]); }); test('items-with-siblings', function(assert) { let fields = commonFields.slice(0, commonFields.length); fields.push('view'); runTest(assert, '#items-spread-across-siblings', fields, [ '423', [ '424', '438', '452', '466', '480', '494', '508', '522', '536' ], 1 ]); }); test('items-across-siblings-with-fields-missing', function(assert) { let fields = commonFields.slice(0, commonFields.length); fields.push('view'); runTest(assert, '#items-across-siblings-fields-missing', fields, [ '552', [ '553', '564', '578', '592', '606', '620', '631', '645', '656' ], 1 ]); }); test('nested-items-with-siblings', function(assert) { let fields = commonFields.slice(0, commonFields.length); fields.push('view'); runTest(assert, '#nested-items-with-siblings', fields, [ '771', [ '773', '787', '801', '816', '830', '844', '859', '873', '887' ], 1 ]); }); test('items-with-field-missing-at-end', function(assert) { runTest(assert, '#items-with-field-missing-at-end', commonFields, [ '672', [ '673', '683', '694', '705', '716', '727', '737', '748', '758' ], 0 ]); }); test('multiple-siblings', function(assert) { let fields = commonFields.slice(0, commonFields.length); fields.push('view'); runTest(assert, '#multiple-siblings', fields, [ '903', [ '904', '921', '938', '955', '972', '989', '1006', '1023', '1040' ], 1 ]); }); test('multiple-siblings-skip-element', function(assert) { let fields = commonFields.slice(0, commonFields.length); fields.push('info'); runTest(assert, '#multiple-siblings', fields, [ '903', [ '904', '921', '938', '955', '972', '989', '1006', '1023', '1040' ], 2 ]); }); skip('transposed-table', function(assert) { runTest(assert, '#transposed-table-structure', commonFields, [ '1060', [ '1062', '0', '0', '0', '0', '0', '0', '0', '0' ], 4 ]); }); test('no-elements-found', function(assert) { runTest(assert, '#doess-not-exist-in-page', commonFields, [ '0', [], 0 ]); }); var testPage = `

    Regular Structure

    Luxury 3 Bed Apartment

    978 Charles Street Barrington, IL 60010

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00

    Renovated 3 Bed Terrace

    237 Myrtle Avenue Aliquippa, PA 15001

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $418000.00

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00

    Detatched 4 Bed Family Residence

    46 Chestnut Street Whitestone, NY 11357

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $586000.00

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00

    Regular Structure With additonal unimportant rows

    Luxury 3 Bed Apartment

    978 Charles Street Barrington, IL 60010

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00
    -

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00
    -

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00
    -

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00
    -

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00
    -

    Renovated 3 Bed Terrace

    237 Myrtle Avenue Aliquippa, PA 15001

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $418000.00
    -

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00
    -

    Detatched 4 Bed Family Residence

    46 Chestnut Street Whitestone, NY 11357

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $586000.00
    -

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00

    Nested Rows and Columns

    Luxury 3 Bed Apartment

    978 Charles Street Barrington, IL 60010

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00

    Renovated 3 Bed Terrace

    237 Myrtle Avenue Aliquippa, PA 15001

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $418000.00

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00

    Detatched 4 Bed Family Residence

    46 Chestnut Street Whitestone, NY 11357

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $586000.00

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00

    Items with Some Fields Missing

    Luxury 3 Bed Apartment

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00

    Renovated 3 Bed Terrace

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $418000.00

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00

    Detatched 4 Bed Family Residence

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $586000.00

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00

    Items Spread across siblings

    Luxury 3 Bed Apartment

    978 Charles Street Barrington, IL 60010

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00
    Number of views: 0

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00
    Number of views: 1

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00
    Number of views: 2

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00
    Number of views: 3

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00
    Number of views: 4

    Renovated 3 Bed Terrace

    237 Myrtle Avenue Aliquippa, PA 15001

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $418000.00
    Number of views: 5

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00
    Number of views: 6

    Detatched 4 Bed Family Residence

    46 Chestnut Street Whitestone, NY 11357

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $586000.00
    Number of views: 7

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00
    Number of views: 8

    Items spread across siblings with some fields missing

    Luxury 3 Bed Apartment

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00
    Number of views: 0

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00
    Number of views: 1

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00
    Number of views: 2

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00
    Number of views: 3

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00
    Number of views: 4

    Renovated 3 Bed Terrace

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $418000.00
    Number of views: 5

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00
    Number of views: 6

    Detatched 4 Bed Family Residence

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $586000.00
    Number of views: 7

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00
    Number of views: 8

    Items with Some Field Missing at End

    Luxury 3 Bed Apartment

    978 Charles Street Barrington, IL 60010

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00

    Renovated 3 Bed Terrace

    237 Myrtle Avenue Aliquippa, PA 15001

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00

    Detatched 4 Bed Family Residence

    46 Chestnut Street Whitestone, NY 11357

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00

    Nested items with internal siblings

    Luxury 3 Bed Apartment

    978 Charles Street Barrington, IL 60010

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00
    Number of views: 0

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00
    Number of views: 1

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00
    Number of views: 2

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00
    Number of views: 0

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00
    Number of views: 1

    Renovated 3 Bed Terrace

    237 Myrtle Avenue Aliquippa, PA 15001

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $418000.00
    Number of views: 2

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00
    Number of views: 0

    Detatched 4 Bed Family Residence

    46 Chestnut Street Whitestone, NY 11357

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $586000.00
    Number of views: 1

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00
    Number of views: 2

    Items spread across multiple siblings

    Luxury 3 Bed Apartment

    978 Charles Street Barrington, IL 60010

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00
    Number of views: 0
    Posted on: January 06 2016

    Upscale Retirement Condo

    609 Prospect Street Rochester, NY 14606

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $353000.00
    Number of views: 1
    Posted on: January 02 2016

    Prestigious 3 Bed Home

    312 Route 29 Hampton, VA 23666

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $300000.00
    Number of views: 2
    Posted on: December 22 2015

    Unique 5 Bed fixer upper

    799 Briarwood Drive Shirley, NY 11967

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $428000.00
    Number of views: 3
    Posted on: December 15 2015

    Splendid 2 Bed Duplex

    102 Tanglewood Drive East Meadow, NY 11554

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $364000.00
    Number of views: 4
    Posted on: December 12 2015

    Renovated 3 Bed Terrace

    237 Myrtle Avenue Aliquippa, PA 15001

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $418000.00
    Number of views: 5
    Posted on: January 03 2016

    Bright Studio Apartment

    117 5th Street North Copperas Cove, TX 76522

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $552000.00
    Number of views: 6
    Posted on: December 23 2015

    Detatched 4 Bed Family Residence

    46 Chestnut Street Whitestone, NY 11357

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $586000.00
    Number of views: 7
    Posted on: January 03 2016

    Superbly designed modern Townhouse

    354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $342000.00
    Number of views: 8
    Posted on: January 05 2016

    Transposed Table Structure

    Luxury 3 Bed Apartment

    Upscale Retirement Condo

    Prestigious 3 Bed Home

    Unique 5 Bed fixer upper

    Splendid 2 Bed Duplex

    Renovated 3 Bed Terrace

    Bright Studio Apartment

    Detatched 4 Bed Family Residence

    Superbly designed modern Townhouse

    978 Charles Street Barrington, IL 60010 609 Prospect Street Rochester, NY 14606 312 Route 29 Hampton, VA 23666 799 Briarwood Drive Shirley, NY 11967 102 Tanglewood Drive East Meadow, NY 11554 237 Myrtle Avenue Aliquippa, PA 15001 117 5th Street North Copperas Cove, TX 76522 46 Chestnut Street Whitestone, NY 11357 354 Church Street South Eastlake, OH 44095

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sit amet congue.

    $215000.00 $353000.00 $300000.00 $428000.00 $364000.00 $418000.00 $552000.00 $586000.00 $342000.00
    `; var doc = Ember.$('').html(testPage).get(0); ================================================ FILE: portiaui/tests/unit/utils/start-urls-test.js ================================================ import { multiplicityFragment } from '../../../utils/start-urls'; import { module, test } from 'qunit'; module('Unit | Utility | startUrls'); test('is correct for a one number range', function(assert) { const fragment = { type: 'range', value: '0-0' }; assert.equal(multiplicityFragment(fragment), 1); }); test('is correct for a large range', function(assert) { const fragment = { type: 'range', value: '0-99' }; assert.equal(multiplicityFragment(fragment), 100); }); test('is correct for a non-zero starting range', function(assert) { const fragment = { type: 'range', value: '51-100' }; assert.equal(multiplicityFragment(fragment), 50); }); ================================================ FILE: portiaui/tests/unit/validators/range-test.js ================================================ import validateRange from '../../../validators/range'; import { module, test } from 'qunit'; module('Unit | Validators | validateRange'); test('it tests valid ranges', function(assert) { const key = 'value'; const validator = validateRange(); assert.equal(validator(key, '1-4'), true); assert.equal(validator(key, 'a-c'), true); assert.equal(validator(key, '5-5'), true); assert.equal(validator(key, 'z-z'), true); }); test('it tests all digits or all letters', function(assert) { const error = 'A range must not mix numbers and letters.'; const key = 'value'; const validator = validateRange(); assert.equal(validator(key, '1-a'), error); assert.equal(validator(key, 'w-3'), error); }); test('it tests completeness', function(assert) { const error = 'A range must have both a start and an end.'; const key = 'value'; const validator = validateRange(); assert.equal(validator(key, '-1'), error); assert.equal(validator(key, '1-'), error); assert.equal(validator(key, '-'), error); assert.equal(validator(key, ''), error); }); test('it tests completeness', function(assert) { const error = 'A range must be increasing.'; const key = 'value'; const validator = validateRange(); assert.equal(validator(key, '10-5'), `${error} Try swapping to 5-10.`); assert.equal(validator(key, 'b-a'), `${error} Try swapping to a-b.`); }); test('it disallows multiple letters', function(assert) { const error = 'A range must have only single letters.'; const key = 'value'; const validator = validateRange(); assert.equal(validator(key, 'a-bc'), error); assert.equal(validator(key, 'asd-z'), error); assert.equal(validator(key, 'aas-zie'), error); }); test('it disallows mixed cases', function(assert) { const error = 'A range cannot mix lower and upper case.'; const key = 'value'; const validator = validateRange(); assert.equal(validator(key, 'a-C'), error); assert.equal(validator(key, 'D-q'), error); }); ================================================ FILE: portiaui/tests/unit/validators/whitespace-test.js ================================================ import validateWhitespace from '../../../validators/whitespace'; import { module, test } from 'qunit'; module('Unit | Validators | validateWhitespace'); test('it should be true without whitespace', function(assert) { const key = 'value'; const validator = validateWhitespace(); assert.equal(validator(key, 'withoutspace'), true); }); test('it should not have whitespace', function(assert) { const error = 'Should not have whitespace'; const key = 'value'; const validator = validateWhitespace(); assert.equal(validator(key, 'with space'), error); assert.equal(validator(key, 'endspace '), error); assert.equal(validator(key, ' startspace'), error); }); ================================================ FILE: portiaui/vendor/.gitkeep ================================================ ================================================ FILE: portiaui/vendor/modernizr.js ================================================ /*! * modernizr v3.3.1 * Build https://modernizr.com/download?-atobbtoa-classlist-cssanimations-csscalc-csspointerevents-csstransforms-csstransitions-cssvhunit-datauri-eventlistener-flexbox-generatedcontent-json-localstorage-nthchild-opacity-placeholder-postmessage-queryselector-requestanimationframe-svg-svgasimg-websockets-dontmin * * Copyright (c) * Faruk Ates * Paul Irish * Alex Sexton * Ryan Seddon * Patrick Kettner * Stu Cox * Richard Herrera * MIT License */ /* * Modernizr tests which native CSS3 and HTML5 features are available in the * current UA and makes the results available to you in two ways: as properties on * a global `Modernizr` object, and as classes on the `` element. This * information allows you to progressively enhance your pages with a granular level * of control over the experience. */ ;(function(window, document, undefined){ var tests = []; /** * * ModernizrProto is the constructor for Modernizr * * @class * @access public */ var ModernizrProto = { // The current version, dummy _version: '3.3.1', // Any settings that don't work as separate modules // can go in here as configuration. _config: { 'classPrefix': '', 'enableClasses': true, 'enableJSClass': true, 'usePrefixes': true }, // Queue of tests _q: [], // Stub these for people who are listening on: function(test, cb) { // I don't really think people should do this, but we can // safe guard it a bit. // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests. // This is in case people listen to synchronous tests. I would leave it out, // but the code to *disallow* sync tests in the real version of this // function is actually larger than this. var self = this; setTimeout(function() { cb(self[test]); }, 0); }, addTest: function(name, fn, options) { tests.push({name: name, fn: fn, options: options}); }, addAsyncTest: function(fn) { tests.push({name: null, fn: fn}); } }; // Fake some of Object.create so we can force non test results to be non "own" properties. var Modernizr = function() {}; Modernizr.prototype = ModernizrProto; // Leak modernizr globally when you `require` it rather than force it here. // Overwrite name so constructor name is nicer :D Modernizr = new Modernizr(); /*! { "name": "Event Listener", "property": "eventlistener", "authors": ["Andrew Betts (@triblondon)"], "notes": [{ "name": "W3C Spec", "href": "https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Registration-interfaces" }], "polyfills": ["eventlistener"] } !*/ /* DOC Detects native support for addEventListener */ Modernizr.addTest('eventlistener', 'addEventListener' in window); /*! { "name": "JSON", "property": "json", "caniuse": "json", "notes": [{ "name": "MDN documentation", "href": "https://developer.mozilla.org/en-US/docs/Glossary/JSON" }], "polyfills": ["json2"] } !*/ /* DOC Detects native support for JSON handling functions. */ // this will also succeed if you've loaded the JSON2.js polyfill ahead of time // ... but that should be obvious. :) Modernizr.addTest('json', 'JSON' in window && 'parse' in JSON && 'stringify' in JSON); /*! { "name": "postMessage", "property": "postmessage", "caniuse": "x-doc-messaging", "notes": [{ "name": "W3C Spec", "href": "http://www.w3.org/TR/html5/comms.html#posting-messages" }], "polyfills": ["easyxdm", "postmessage-jquery"] } !*/ /* DOC Detects support for the `window.postMessage` protocol for cross-document messaging. */ Modernizr.addTest('postmessage', 'postMessage' in window); /*! { "name": "QuerySelector", "property": "queryselector", "caniuse": "queryselector", "tags": ["queryselector"], "authors": ["Andrew Betts (@triblondon)"], "notes": [{ "name" : "W3C Selectors reference", "href": "https://www.w3.org/TR/selectors-api/#queryselectorall" }], "polyfills": ["css-selector-engine"] } !*/ /* DOC Detects support for querySelector. */ Modernizr.addTest('queryselector', 'querySelector' in document && 'querySelectorAll' in document); /*! { "name": "SVG", "property": "svg", "caniuse": "svg", "tags": ["svg"], "authors": ["Erik Dahlstrom"], "polyfills": [ "svgweb", "raphael", "amplesdk", "canvg", "svg-boilerplate", "sie", "dojogfx", "fabricjs" ] } !*/ /* DOC Detects support for SVG in `` or `` elements. */ Modernizr.addTest('svg', !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect); /*! { "name": "WebSockets Support", "property": "websockets", "authors": ["Phread [fearphage]", "Mike Sherov [mikesherov]", "Burak Yigit Kaya [BYK]"], "caniuse": "websockets", "tags": ["html5"], "warnings": [ "This test will reject any old version of WebSockets even if it is not prefixed such as in Safari 5.1" ], "notes": [{ "name": "CLOSING State and Spec", "href": "https://www.w3.org/TR/websockets/#the-websocket-interface" }], "polyfills": [ "sockjs", "socketio", "kaazing-websocket-gateway", "websocketjs", "atmosphere", "graceful-websocket", "portal", "datachannel" ] } !*/ var supports = false; try { supports = 'WebSocket' in window && window.WebSocket.CLOSING === 2; } catch (e) {} Modernizr.addTest('websockets', supports); /*! { "name": "Local Storage", "property": "localstorage", "caniuse": "namevalue-storage", "tags": ["storage"], "knownBugs": [], "notes": [], "warnings": [], "polyfills": [ "joshuabell-polyfill", "cupcake", "storagepolyfill", "amplifyjs", "yui-cacheoffline" ] } !*/ // In FF4, if disabled, window.localStorage should === null. // Normally, we could not test that directly and need to do a // `('localStorage' in window) && ` test first because otherwise Firefox will // throw bugzil.la/365772 if cookies are disabled // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem // will throw the exception: // QUOTA_EXCEEDED_ERROR DOM Exception 22. // Peculiarly, getItem and removeItem calls do not throw. // Because we are forced to try/catch this, we'll go aggressive. // Just FWIW: IE8 Compat mode supports these features completely: // www.quirksmode.org/dom/html5.html // But IE8 doesn't support either with local files Modernizr.addTest('localstorage', function() { var mod = 'modernizr'; try { localStorage.setItem(mod, mod); localStorage.removeItem(mod); return true; } catch (e) { return false; } }); var classes = []; /** * is returns a boolean if the typeof an obj is exactly type. * * @access private * @function is * @param {*} obj - A thing we want to check the type of * @param {string} type - A string to compare the typeof against * @returns {boolean} */ function is(obj, type) { return typeof obj === type; } ; /** * Run through all tests and detect their support in the current UA. * * @access private */ function testRunner() { var featureNames; var feature; var aliasIdx; var result; var nameIdx; var featureName; var featureNameSplit; for (var featureIdx in tests) { if (tests.hasOwnProperty(featureIdx)) { featureNames = []; feature = tests[featureIdx]; // run the test, throw the return value into the Modernizr, // then based on that boolean, define an appropriate className // and push it into an array of classes we'll join later. // // If there is no name, it's an 'async' test that is run, // but not directly added to the object. That should // be done with a post-run addTest call. if (feature.name) { featureNames.push(feature.name.toLowerCase()); if (feature.options && feature.options.aliases && feature.options.aliases.length) { // Add all the aliases into the names list for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) { featureNames.push(feature.options.aliases[aliasIdx].toLowerCase()); } } } // Run the test, or use the raw value if it's not a function result = is(feature.fn, 'function') ? feature.fn() : feature.fn; // Set each of the names on the Modernizr object for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) { featureName = featureNames[nameIdx]; // Support dot properties as sub tests. We don't do checking to make sure // that the implied parent tests have been added. You must call them in // order (either in the test, or make the parent test a dependency). // // Cap it to TWO to make the logic simple and because who needs that kind of subtesting // hashtag famous last words featureNameSplit = featureName.split('.'); if (featureNameSplit.length === 1) { Modernizr[featureNameSplit[0]] = result; } else { // cast to a Boolean, if not one already /* jshint -W053 */ if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) { Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]); } Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result; } classes.push((result ? '' : 'no-') + featureNameSplit.join('-')); } } } } ; /** * List of property values to set for css tests. See ticket #21 * http://git.io/vUGl4 * * @memberof Modernizr * @name Modernizr._prefixes * @optionName Modernizr._prefixes * @optionProp prefixes * @access public * @example * * Modernizr._prefixes is the internal list of prefixes that we test against * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply * an array of kebab-case vendor prefixes you can use within your code. * * Some common use cases include * * Generating all possible prefixed version of a CSS property * ```js * var rule = Modernizr._prefixes.join('transform: rotate(20deg); '); * * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);' * ``` * * Generating all possible prefixed version of a CSS value * ```js * rule = 'display:' + Modernizr._prefixes.join('flex; display:') + 'flex'; * * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex' * ``` */ // we use ['',''] rather than an empty array in order to allow a pattern of .`join()`ing prefixes to test // values in feature detects to continue to work var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : ['','']); // expose these for the plugin API. Look in the source for how to join() them against your input ModernizrProto._prefixes = prefixes; /** * docElement is a convenience wrapper to grab the root element of the document * * @access private * @returns {HTMLElement|SVGElement} The root element of the document */ var docElement = document.documentElement; /*! { "name": "classList", "caniuse": "classlist", "property": "classlist", "tags": ["dom"], "builderAliases": ["dataview_api"], "notes": [{ "name": "MDN Docs", "href": "https://developer.mozilla.org/en/DOM/element.classList" }] } !*/ Modernizr.addTest('classlist', 'classList' in docElement); /** * cssToDOM takes a kebab-case string and converts it to camelCase * e.g. box-sizing -> boxSizing * * @access private * @function cssToDOM * @param {string} name - String name of kebab-case prop we want to convert * @returns {string} The camelCase version of the supplied name */ function cssToDOM(name) { return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) { return m1 + m2.toUpperCase(); }).replace(/^-/, ''); } ; /** * A convenience helper to check if the document we are running in is an SVG document * * @access private * @returns {boolean} */ var isSVG = docElement.nodeName.toLowerCase() === 'svg'; /** * createElement is a convenience wrapper around document.createElement. Since we * use createElement all over the place, this allows for (slightly) smaller code * as well as abstracting away issues with creating elements in contexts other than * HTML documents (e.g. SVG documents). * * @access private * @function createElement * @returns {HTMLElement|SVGElement} An HTML or SVG element */ function createElement() { if (typeof document.createElement !== 'function') { // This is the case in IE7, where the type of createElement is "object". // For this reason, we cannot call apply() as Object is not a Function. return document.createElement(arguments[0]); } else if (isSVG) { return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]); } else { return document.createElement.apply(document, arguments); } } ; /*! { "name": "CSS Calc", "property": "csscalc", "caniuse": "calc", "tags": ["css"], "builderAliases": ["css_calc"], "authors": ["@calvein"] } !*/ /* DOC Method of allowing calculated values for length units. For example: ```css //lem { width: calc(100% - 3em); } ``` */ Modernizr.addTest('csscalc', function() { var prop = 'width:'; var value = 'calc(10px);'; var el = createElement('a'); el.style.cssText = prop + prefixes.join(value + prop); return !!el.style.length; }); /*! { "name": "CSS Opacity", "caniuse": "css-opacity", "property": "opacity", "tags": ["css"] } !*/ // Browsers that actually have CSS Opacity implemented have done so // according to spec, which means their return values are within the // range of [0.0,1.0] - including the leading zero. Modernizr.addTest('opacity', function() { var style = createElement('a').style; style.cssText = prefixes.join('opacity:.55;'); // The non-literal . in this regex is intentional: // German Chrome returns this value as 0,55 // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 return (/^0.55$/).test(style.opacity); }); /*! { "name": "CSS Pointer Events", "caniuse": "pointer-events", "property": "csspointerevents", "authors": ["ausi"], "tags": ["css"], "builderAliases": ["css_pointerevents"], "notes": [ { "name": "MDN Docs", "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" },{ "name": "Test Project Page", "href": "https://ausi.github.com/Feature-detection-technique-for-pointer-events/" },{ "name": "Test Project Wiki", "href": "https://github.com/ausi/Feature-detection-technique-for-pointer-events/wiki" }, { "name": "Related Github Issue", "href": "https://github.com/Modernizr/Modernizr/issues/80" } ] } !*/ Modernizr.addTest('csspointerevents', function() { var style = createElement('a').style; style.cssText = 'pointer-events:auto'; return style.pointerEvents === 'auto'; }); /*! { "name": "placeholder attribute", "property": "placeholder", "tags": ["forms", "attribute"], "builderAliases": ["forms_placeholder"] } !*/ /* DOC Tests for placeholder attribute in inputs and textareas */ Modernizr.addTest('placeholder', ('placeholder' in createElement('input') && 'placeholder' in createElement('textarea'))); /** * hasOwnProp is a shim for hasOwnProperty that is needed for Safari 2.0 support * * @author kangax * @access private * @function hasOwnProp * @param {object} object - The object to check for a property * @param {string} property - The property to check for * @returns {boolean} */ // hasOwnProperty shim by kangax needed for Safari 2.0 support var hasOwnProp; (function() { var _hasOwnProperty = ({}).hasOwnProperty; /* istanbul ignore else */ /* we have no way of testing IE 5.5 or safari 2, * so just assume the else gets hit */ if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) { hasOwnProp = function(object, property) { return _hasOwnProperty.call(object, property); }; } else { hasOwnProp = function(object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ return ((property in object) && is(object.constructor.prototype[property], 'undefined')); }; } })(); /** * setClasses takes an array of class names and adds them to the root element * * @access private * @function setClasses * @param {string[]} classes - Array of class names */ // Pass in an and array of class names, e.g.: // ['no-webp', 'borderradius', ...] function setClasses(classes) { var className = docElement.className; var classPrefix = Modernizr._config.classPrefix || ''; if (isSVG) { className = className.baseVal; } // Change `no-js` to `js` (independently of the `enableClasses` option) // Handle classPrefix on this too if (Modernizr._config.enableJSClass) { var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)'); className = className.replace(reJS, '$1' + classPrefix + 'js$2'); } if (Modernizr._config.enableClasses) { // Add the new classes className += ' ' + classPrefix + classes.join(' ' + classPrefix); isSVG ? docElement.className.baseVal = className : docElement.className = className; } } ; // _l tracks listeners for async tests, as well as tests that execute after the initial run ModernizrProto._l = {}; /** * Modernizr.on is a way to listen for the completion of async tests. Being * asynchronous, they may not finish before your scripts run. As a result you * will get a possibly false negative `undefined` value. * * @memberof Modernizr * @name Modernizr.on * @access public * @function on * @param {string} feature - String name of the feature detect * @param {function} cb - Callback function returning a Boolean - true if feature is supported, false if not * @example * * ```js * Modernizr.on('flash', function( result ) { * if (result) { * // the browser has flash * } else { * // the browser does not have flash * } * }); * ``` */ ModernizrProto.on = function(feature, cb) { // Create the list of listeners if it doesn't exist if (!this._l[feature]) { this._l[feature] = []; } // Push this test on to the listener list this._l[feature].push(cb); // If it's already been resolved, trigger it on next tick if (Modernizr.hasOwnProperty(feature)) { // Next Tick setTimeout(function() { Modernizr._trigger(feature, Modernizr[feature]); }, 0); } }; /** * _trigger is the private function used to signal test completion and run any * callbacks registered through [Modernizr.on](#modernizr-on) * * @memberof Modernizr * @name Modernizr._trigger * @access private * @function _trigger * @param {string} feature - string name of the feature detect * @param {function|boolean} [res] - A feature detection function, or the boolean = * result of a feature detection function */ ModernizrProto._trigger = function(feature, res) { if (!this._l[feature]) { return; } var cbs = this._l[feature]; // Force async setTimeout(function() { var i, cb; for (i = 0; i < cbs.length; i++) { cb = cbs[i]; cb(res); } }, 0); // Don't trigger these again delete this._l[feature]; }; /** * addTest allows you to define your own feature detects that are not currently * included in Modernizr (under the covers it's the exact same code Modernizr * uses for its own [feature detections](https://github.com/Modernizr/Modernizr/tree/master/feature-detects)). Just like the offical detects, the result * will be added onto the Modernizr object, as well as an appropriate className set on * the html element when configured to do so * * @memberof Modernizr * @name Modernizr.addTest * @optionName Modernizr.addTest() * @optionProp addTest * @access public * @function addTest * @param {string|object} feature - The string name of the feature detect, or an * object of feature detect names and test * @param {function|boolean} test - Function returning true if feature is supported, * false if not. Otherwise a boolean representing the results of a feature detection * @example * * The most common way of creating your own feature detects is by calling * `Modernizr.addTest` with a string (preferably just lowercase, without any * punctuation), and a function you want executed that will return a boolean result * * ```js * Modernizr.addTest('itsTuesday', function() { * var d = new Date(); * return d.getDay() === 2; * }); * ``` * * When the above is run, it will set Modernizr.itstuesday to `true` when it is tuesday, * and to `false` every other day of the week. One thing to notice is that the names of * feature detect functions are always lowercased when added to the Modernizr object. That * means that `Modernizr.itsTuesday` will not exist, but `Modernizr.itstuesday` will. * * * Since we only look at the returned value from any feature detection function, * you do not need to actually use a function. For simple detections, just passing * in a statement that will return a boolean value works just fine. * * ```js * Modernizr.addTest('hasJquery', 'jQuery' in window); * ``` * * Just like before, when the above runs `Modernizr.hasjquery` will be true if * jQuery has been included on the page. Not using a function saves a small amount * of overhead for the browser, as well as making your code much more readable. * * Finally, you also have the ability to pass in an object of feature names and * their tests. This is handy if you want to add multiple detections in one go. * The keys should always be a string, and the value can be either a boolean or * function that returns a boolean. * * ```js * var detects = { * 'hasjquery': 'jQuery' in window, * 'itstuesday': function() { * var d = new Date(); * return d.getDay() === 2; * } * } * * Modernizr.addTest(detects); * ``` * * There is really no difference between the first methods and this one, it is * just a convenience to let you write more readable code. */ function addTest(feature, test) { if (typeof feature == 'object') { for (var key in feature) { if (hasOwnProp(feature, key)) { addTest(key, feature[ key ]); } } } else { feature = feature.toLowerCase(); var featureNameSplit = feature.split('.'); var last = Modernizr[featureNameSplit[0]]; // Again, we don't check for parent test existence. Get that right, though. if (featureNameSplit.length == 2) { last = last[featureNameSplit[1]]; } if (typeof last != 'undefined') { // we're going to quit if you're trying to overwrite an existing test // if we were to allow it, we'd do this: // var re = new RegExp("\\b(no-)?" + feature + "\\b"); // docElement.className = docElement.className.replace( re, '' ); // but, no rly, stuff 'em. return Modernizr; } test = typeof test == 'function' ? test() : test; // Set the value (this is the magic, right here). if (featureNameSplit.length == 1) { Modernizr[featureNameSplit[0]] = test; } else { // cast to a Boolean, if not one already /* jshint -W053 */ if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) { Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]); } Modernizr[featureNameSplit[0]][featureNameSplit[1]] = test; } // Set a single class (either `feature` or `no-feature`) /* jshint -W041 */ setClasses([(!!test && test != false ? '' : 'no-') + featureNameSplit.join('-')]); /* jshint +W041 */ // Trigger the event Modernizr._trigger(feature, test); } return Modernizr; // allow chaining. } // After all the tests are run, add self to the Modernizr prototype Modernizr._q.push(function() { ModernizrProto.addTest = addTest; }); /*! { "name": "SVG as an tag source", "property": "svgasimg", "caniuse" : "svg-img", "tags": ["svg"], "authors": ["Chris Coyier"], "notes": [{ "name": "HTML5 Spec", "href": "http://www.w3.org/TR/html5/embedded-content-0.html#the-img-element" }] } !*/ // Original Async test by Stu Cox // https://gist.github.com/chriscoyier/8774501 // Now a Sync test based on good results here // http://codepen.io/chriscoyier/pen/bADFx // Note http://www.w3.org/TR/SVG11/feature#Image is *supposed* to represent // support for the `` tag in SVG, not an SVG file linked from an `` // tag in HTML – but it’s a heuristic which works Modernizr.addTest('svgasimg', document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Image', '1.1')); /*! { "name": "Data URI", "property": "datauri", "caniuse": "datauri", "tags": ["url"], "builderAliases": ["url_data_uri"], "async": true, "notes": [{ "name": "Wikipedia article", "href": "https://en.wikipedia.org/wiki/Data_URI_scheme" }], "warnings": ["Support in Internet Explorer 8 is limited to images and linked resources like CSS files, not HTML files"] } !*/ /* DOC Detects support for data URIs. Provides a subproperty to report support for data URIs over 32kb in size: ```javascript Modernizr.datauri // true Modernizr.datauri.over32kb // false in IE8 ``` */ // https://github.com/Modernizr/Modernizr/issues/14 Modernizr.addAsyncTest(function() { /* jshint -W053 */ // IE7 throw a mixed content warning on HTTPS for this test, so we'll // just blacklist it (we know it doesn't support data URIs anyway) // https://github.com/Modernizr/Modernizr/issues/362 if (navigator.userAgent.indexOf('MSIE 7.') !== -1) { // Keep the test async setTimeout(function() { addTest('datauri', false); }, 10); } var datauri = new Image(); datauri.onerror = function() { addTest('datauri', false); }; datauri.onload = function() { if (datauri.width == 1 && datauri.height == 1) { testOver32kb(); } else { addTest('datauri', false); } }; datauri.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='; // Once we have datauri, let's check to see if we can use data URIs over // 32kb (IE8 can't). https://github.com/Modernizr/Modernizr/issues/321 function testOver32kb() { var datauriBig = new Image(); datauriBig.onerror = function() { addTest('datauri', true); Modernizr.datauri = new Boolean(true); Modernizr.datauri.over32kb = false; }; datauriBig.onload = function() { addTest('datauri', true); Modernizr.datauri = new Boolean(true); Modernizr.datauri.over32kb = (datauriBig.width == 1 && datauriBig.height == 1); }; var base64str = 'R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='; while (base64str.length < 33000) { base64str = '\r\n' + base64str; } datauriBig.src = 'data:image/gif;base64,' + base64str; } }); /** * getBody returns the body of a document, or an element that can stand in for * the body if a real body does not exist * * @access private * @function getBody * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an * artificially created element that stands in for the body */ function getBody() { // After page load injecting a fake body doesn't work so check if body exists var body = document.body; if (!body) { // Can't use the real body create a fake one. body = createElement(isSVG ? 'svg' : 'body'); body.fake = true; } return body; } ; /** * injectElementWithStyles injects an element with style element and some CSS rules * * @access private * @function injectElementWithStyles * @param {string} rule - String representing a css rule * @param {function} callback - A function that is used to test the injected element * @param {number} [nodes] - An integer representing the number of additional nodes you want injected * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes * @returns {boolean} */ function injectElementWithStyles(rule, callback, nodes, testnames) { var mod = 'modernizr'; var style; var ret; var node; var docOverflow; var div = createElement('div'); var body = getBody(); if (parseInt(nodes, 10)) { // In order not to give false positives we create a node for each test // This also allows the method to scale for unspecified uses while (nodes--) { node = createElement('div'); node.id = testnames ? testnames[nodes] : mod + (nodes + 1); div.appendChild(node); } } style = createElement('style'); style.type = 'text/css'; style.id = 's' + mod; // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 (!body.fake ? div : body).appendChild(style); body.appendChild(div); if (style.styleSheet) { style.styleSheet.cssText = rule; } else { style.appendChild(document.createTextNode(rule)); } div.id = mod; if (body.fake) { //avoid crashing IE8, if background image is used body.style.background = ''; //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible body.style.overflow = 'hidden'; docOverflow = docElement.style.overflow; docElement.style.overflow = 'hidden'; docElement.appendChild(body); } ret = callback(div, rule); // If this is done after page load we don't want to remove the body so check if body exists if (body.fake) { body.parentNode.removeChild(body); docElement.style.overflow = docOverflow; // Trigger layout so kinetic scrolling isn't disabled in iOS6+ docElement.offsetHeight; } else { div.parentNode.removeChild(div); } return !!ret; } ; /** * testStyles injects an element with style element and some CSS rules * * @memberof Modernizr * @name Modernizr.testStyles * @optionName Modernizr.testStyles() * @optionProp testStyles * @access public * @function testStyles * @param {string} rule - String representing a css rule * @param {function} callback - A function that is used to test the injected element * @param {number} [nodes] - An integer representing the number of additional nodes you want injected * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes * @returns {boolean} * @example * * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page * along with (possibly multiple) DOM elements. This lets you check for features * that can not be detected by simply checking the [IDL](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Interface_development_guide/IDL_interface_rules). * * ```js * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) { * // elem is the first DOM node in the page (by default #modernizr) * // rule is the first argument you supplied - the CSS rule in string form * * addTest('widthworks', elem.style.width === '9px') * }); * ``` * * If your test requires multiple nodes, you can include a third argument * indicating how many additional div elements to include on the page. The * additional nodes are injected as children of the `elem` that is returned as * the first argument to the callback. * * ```js * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) { * document.getElementById('modernizr').style.width === '1px'; // true * document.getElementById('modernizr2').style.width === '2px'; // true * elem.firstChild === document.getElementById('modernizr2'); // true * }, 1); * ``` * * By default, all of the additional elements have an ID of `modernizr[n]`, where * `n` is its index (e.g. the first additional, second overall is `#modernizr2`, * the second additional is `#modernizr3`, etc.). * If you want to have more meaningful IDs for your function, you can provide * them as the fourth argument, as an array of strings * * ```js * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) { * elem.firstChild === document.getElementById('foo'); // true * elem.lastChild === document.getElementById('bar'); // true * }, 2, ['foo', 'bar']); * ``` * */ var testStyles = ModernizrProto.testStyles = injectElementWithStyles; /*! { "name": "CSS Generated Content", "property": "generatedcontent", "tags": ["css"], "warnings": ["Android won't return correct height for anything below 7px #738"], "notes": [{ "name": "W3C CSS Selectors Level 3 spec", "href": "https://www.w3.org/TR/css3-selectors/#gen-content" },{ "name": "MDN article on :before", "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/::before" },{ "name": "MDN article on :after", "href": "https://developer.mozilla.org/en-US/docs/Web/CSS/::before" }] } !*/ testStyles('#modernizr{font:0/0 a}#modernizr:after{content:":)";visibility:hidden;font:7px/1 a}', function(node) { Modernizr.addTest('generatedcontent', node.offsetHeight >= 7); }); /*! { "name": "CSS :nth-child pseudo-selector", "caniuse": "css-sel3", "property": "nthchild", "tags": ["css"], "notes": [ { "name": "Related Github Issue", "href": "https://github.com/Modernizr/Modernizr/pull/685" }, { "name": "Sitepoint :nth-child documentation", "href": "http://reference.sitepoint.com/css/pseudoclass-nthchild" } ], "authors": ["@emilchristensen"], "warnings": ["Known false negative in Safari 3.1 and Safari 3.2.2"] } !*/ /* DOC Detects support for the ':nth-child()' CSS pseudo-selector. */ // 5 `
    ` elements with `1px` width are created. // Then every other element has its `width` set to `2px`. // A Javascript loop then tests if the `
    `s have the expected width // using the modulus operator. testStyles('#modernizr div {width:1px} #modernizr div:nth-child(2n) {width:2px;}', function(elem) { var elems = elem.getElementsByTagName('div'); var correctWidths = true; for (var i = 0; i < 5; i++) { correctWidths = correctWidths && elems[i].offsetWidth === i % 2 + 1; } Modernizr.addTest('nthchild', correctWidths); }, 5); /*! { "name": "CSS vh unit", "property": "cssvhunit", "caniuse": "viewport-units", "tags": ["css"], "builderAliases": ["css_vhunit"], "notes": [{ "name": "Related Modernizr Issue", "href": "https://github.com/Modernizr/Modernizr/issues/572" },{ "name": "Similar JSFiddle", "href": "https://jsfiddle.net/FWeinb/etnYC/" }] } !*/ testStyles('#modernizr { height: 50vh; }', function(elem) { var height = parseInt(window.innerHeight / 2, 10); var compStyle = parseInt((window.getComputedStyle ? getComputedStyle(elem, null) : elem.currentStyle).height, 10); Modernizr.addTest('cssvhunit', compStyle == height); }); /** * If the browsers follow the spec, then they would expose vendor-specific style as: * elem.style.WebkitBorderRadius * instead of something like the following, which would be technically incorrect: * elem.style.webkitBorderRadius * Webkit ghosts their properties in lowercase but Opera & Moz do not. * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ * erik.eae.net/archives/2008/03/10/21.48.10/ * More here: github.com/Modernizr/Modernizr/issues/issue/21 * * @access private * @returns {string} The string representing the vendor-specific style properties */ var omPrefixes = 'Moz O ms Webkit'; var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []); ModernizrProto._cssomPrefixes = cssomPrefixes; /** * atRule returns a given CSS property at-rule (eg @keyframes), possibly in * some prefixed form, or false, in the case of an unsupported rule * * @memberof Modernizr * @name Modernizr.atRule * @optionName Modernizr.atRule() * @optionProp atRule * @access public * @function atRule * @param {string} prop - String name of the @-rule to test for * @returns {string|boolean} The string representing the (possibly prefixed) * valid version of the @-rule, or `false` when it is unsupported. * @example * ```js * var keyframes = Modernizr.atRule('@keyframes'); * * if (keyframes) { * // keyframes are supported * // could be `@-webkit-keyframes` or `@keyframes` * } else { * // keyframes === `false` * } * ``` * */ var atRule = function(prop) { var length = prefixes.length; var cssrule = window.CSSRule; var rule; if (typeof cssrule === 'undefined') { return undefined; } if (!prop) { return false; } // remove literal @ from beginning of provided property prop = prop.replace(/^@/, ''); // CSSRules use underscores instead of dashes rule = prop.replace(/-/g, '_').toUpperCase() + '_RULE'; if (rule in cssrule) { return '@' + prop; } for (var i = 0; i < length; i++) { // prefixes gives us something like -o-, and we want O_ var prefix = prefixes[i]; var thisRule = prefix.toUpperCase() + '_' + rule; if (thisRule in cssrule) { return '@-' + prefix.toLowerCase() + '-' + prop; } } return false; }; ModernizrProto.atRule = atRule; /** * List of JavaScript DOM values used for tests * * @memberof Modernizr * @name Modernizr._domPrefixes * @optionName Modernizr._domPrefixes * @optionProp domPrefixes * @access public * @example * * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather * than kebab-case properties, all properties are their Capitalized variant * * ```js * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ]; * ``` */ var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []); ModernizrProto._domPrefixes = domPrefixes; /** * contains checks to see if a string contains another string * * @access private * @function contains * @param {string} str - The string we want to check for substrings * @param {string} substr - The substring we want to search the first string for * @returns {boolean} */ function contains(str, substr) { return !!~('' + str).indexOf(substr); } ; /** * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill. * * @access private * @function fnBind * @param {function} fn - a function you want to change `this` reference to * @param {object} that - the `this` you want to call the function with * @returns {function} The wrapped version of the supplied function */ function fnBind(fn, that) { return function() { return fn.apply(that, arguments); }; } ; /** * testDOMProps is a generic DOM property test; if a browser supports * a certain property, it won't return undefined for it. * * @access private * @function testDOMProps * @param {array.} props - An array of properties to test for * @param {object} obj - An object or Element you want to use to test the parameters again * @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check */ function testDOMProps(props, obj, elem) { var item; for (var i in props) { if (props[i] in obj) { // return the property name as a string if (elem === false) { return props[i]; } item = obj[props[i]]; // let's bind a function if (is(item, 'function')) { // bind to obj unless overriden return fnBind(item, elem || obj); } // return the unbound function or obj or value return item; } } return false; } ; /** * Create our "modernizr" element that we do most feature tests on. * * @access private */ var modElem = { elem: createElement('modernizr') }; // Clean up this element Modernizr._q.push(function() { delete modElem.elem; }); var mStyle = { style: modElem.elem.style }; // kill ref for gc, must happen before mod.elem is removed, so we unshift on to // the front of the queue. Modernizr._q.unshift(function() { delete mStyle.style; }); /*! { "name": "Base 64 encoding/decoding", "property": ["atobbtoa"], "builderAliases": ["atob-btoa"], "caniuse" : "atob-btoa", "tags": ["atob", "base64", "WindowBase64", "btoa"], "authors": ["Christian Ulbrich"], "notes": [{ "name": "WindowBase64", "href": "https://www.w3.org/TR/html5/webappapis.html#windowbase64" }, { "name": "MDN documentation", "href": "https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/atob" }], "polyfills": ["base64js"] } !*/ /* DOC Detects support for WindowBase64 API (window.atob && window.btoa). */ Modernizr.addTest('atobbtoa', 'atob' in window && 'btoa' in window, {aliases: ['atob-btoa']}); /** * domToCSS takes a camelCase string and converts it to kebab-case * e.g. boxSizing -> box-sizing * * @access private * @function domToCSS * @param {string} name - String name of camelCase prop we want to convert * @returns {string} The kebab-case version of the supplied name */ function domToCSS(name) { return name.replace(/([A-Z])/g, function(str, m1) { return '-' + m1.toLowerCase(); }).replace(/^ms-/, '-ms-'); } ; /** * nativeTestProps allows for us to use native feature detection functionality if available. * some prefixed form, or false, in the case of an unsupported rule * * @access private * @function nativeTestProps * @param {array} props - An array of property names * @param {string} value - A string representing the value we want to check via @supports * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise */ // Accepts a list of property names and a single value // Returns `undefined` if native detection not available function nativeTestProps(props, value) { var i = props.length; // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface if ('CSS' in window && 'supports' in window.CSS) { // Try every prefixed variant of the property while (i--) { if (window.CSS.supports(domToCSS(props[i]), value)) { return true; } } return false; } // Otherwise fall back to at-rule (for Opera 12.x) else if ('CSSSupportsRule' in window) { // Build a condition string for every prefixed variant var conditionText = []; while (i--) { conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')'); } conditionText = conditionText.join(' or '); return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) { return getComputedStyle(node, null).position == 'absolute'; }); } return undefined; } ; // testProps is a generic CSS / DOM property test. // In testing support for a given CSS property, it's legit to test: // `elem.style[styleName] !== undefined` // If the property is supported it will return an empty string, // if unsupported it will return undefined. // We'll take advantage of this quick test and skip setting a style // on our modernizr element, but instead just testing undefined vs // empty string. // Property names can be provided in either camelCase or kebab-case. function testProps(props, prefixed, value, skipValueTest) { skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest; // Try native detect first if (!is(value, 'undefined')) { var result = nativeTestProps(props, value); if (!is(result, 'undefined')) { return result; } } // Otherwise do it properly var afterInit, i, propsLength, prop, before; // If we don't have a style element, that means we're running async or after // the core tests, so we'll need to create our own elements to use // inside of an SVG element, in certain browsers, the `style` element is only // defined for valid tags. Therefore, if `modernizr` does not have one, we // fall back to a less used element and hope for the best. // for strict XHTML browsers the hardly used samp element is used var elems = ['modernizr', 'tspan', 'samp']; while (!mStyle.style && elems.length) { afterInit = true; mStyle.modElem = createElement(elems.shift()); mStyle.style = mStyle.modElem.style; } // Delete the objects if we created them. function cleanElems() { if (afterInit) { delete mStyle.style; delete mStyle.modElem; } } propsLength = props.length; for (i = 0; i < propsLength; i++) { prop = props[i]; before = mStyle.style[prop]; if (contains(prop, '-')) { prop = cssToDOM(prop); } if (mStyle.style[prop] !== undefined) { // If value to test has been passed in, do a set-and-check test. // 0 (integer) is a valid property value, so check that `value` isn't // undefined, rather than just checking it's truthy. if (!skipValueTest && !is(value, 'undefined')) { // Needs a try catch block because of old IE. This is slow, but will // be avoided in most cases because `skipValueTest` will be used. try { mStyle.style[prop] = value; } catch (e) {} // If the property value has changed, we assume the value used is // supported. If `value` is empty string, it'll fail here (because // it hasn't changed), which matches how browsers have implemented // CSS.supports() if (mStyle.style[prop] != before) { cleanElems(); return prefixed == 'pfx' ? prop : true; } } // Otherwise just return true, or the property name if this is a // `prefixed()` call else { cleanElems(); return prefixed == 'pfx' ? prop : true; } } } cleanElems(); return false; } ; /** * testPropsAll tests a list of DOM properties we want to check against. * We specify literally ALL possible (known and/or likely) properties on * the element including the non-vendor prefixed one, for forward- * compatibility. * * @access private * @function testPropsAll * @param {string} prop - A string of the property to test for * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against * @param {string} [value] - A string of a css value * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set */ function testPropsAll(prop, prefixed, elem, value, skipValueTest) { var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); // did they call .prefixed('boxSizing') or are we just testing a prop? if (is(prefixed, 'string') || is(prefixed, 'undefined')) { return testProps(props, prefixed, value, skipValueTest); // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) } else { props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); return testDOMProps(props, prefixed, elem); } } // Modernizr.testAllProps() investigates whether a given style property, // or any of its vendor-prefixed variants, is recognized // // Note that the property names must be provided in the camelCase variant. // Modernizr.testAllProps('boxSizing') ModernizrProto.testAllProps = testPropsAll; /** * prefixed returns the prefixed or nonprefixed property name variant of your input * * @memberof Modernizr * @name Modernizr.prefixed * @optionName Modernizr.prefixed() * @optionProp prefixed * @access public * @function prefixed * @param {string} prop - String name of the property to test for * @param {object} [obj] - An object to test for the prefixed properties on * @param {HTMLElement} [elem] - An element used to test specific properties against * @returns {string|false} The string representing the (possibly prefixed) valid * version of the property, or `false` when it is unsupported. * @example * * Modernizr.prefixed takes a string css value in the DOM style camelCase (as * opposed to the css style kebab-case) form and returns the (possibly prefixed) * version of that property that the browser actually supports. * * For example, in older Firefox... * ```js * prefixed('boxSizing') * ``` * returns 'MozBoxSizing' * * In newer Firefox, as well as any other browser that support the unprefixed * version would simply return `boxSizing`. Any browser that does not support * the property at all, it will return `false`. * * By default, prefixed is checked against a DOM element. If you want to check * for a property on another object, just pass it as a second argument * * ```js * var rAF = prefixed('requestAnimationFrame', window); * * raf(function() { * renderFunction(); * }) * ``` * * Note that this will return _the actual function_ - not the name of the function. * If you need the actual name of the property, pass in `false` as a third argument * * ```js * var rAFProp = prefixed('requestAnimationFrame', window, false); * * rafProp === 'WebkitRequestAnimationFrame' // in older webkit * ``` * * One common use case for prefixed is if you're trying to determine which transition * end event to bind to, you might do something like... * ```js * var transEndEventNames = { * 'WebkitTransition' : 'webkitTransitionEnd', * Saf 6, Android Browser * 'MozTransition' : 'transitionend', * only for FF < 15 * 'transition' : 'transitionend' * IE10, Opera, Chrome, FF 15+, Saf 7+ * }; * * var transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; * ``` * * If you want a similar lookup, but in kebab-case, you can use [prefixedCSS](#modernizr-prefixedcss). */ var prefixed = ModernizrProto.prefixed = function(prop, obj, elem) { if (prop.indexOf('@') === 0) { return atRule(prop); } if (prop.indexOf('-') != -1) { // Convert kebab-case to camelCase prop = cssToDOM(prop); } if (!obj) { return testPropsAll(prop, 'pfx'); } else { // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' return testPropsAll(prop, obj, elem); } }; /*! { "name": "requestAnimationFrame", "property": "requestanimationframe", "aliases": ["raf"], "caniuse": "requestanimationframe", "tags": ["animation"], "authors": ["Addy Osmani"], "notes": [{ "name": "W3C spec", "href": "https://www.w3.org/TR/animation-timing/" }], "polyfills": ["raf"] } !*/ /* DOC Detects support for the `window.requestAnimationFrame` API, for offloading animation repainting to the browser for optimized performance. */ Modernizr.addTest('requestanimationframe', !!prefixed('requestAnimationFrame', window), {aliases: ['raf']}); /** * testAllProps determines whether a given CSS property is supported in the browser * * @memberof Modernizr * @name Modernizr.testAllProps * @optionName Modernizr.testAllProps() * @optionProp testAllProps * @access public * @function testAllProps * @param {string} prop - String naming the property to test (either camelCase or kebab-case) * @param {string} [value] - String of the value to test * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection * @example * * testAllProps determines whether a given CSS property, in some prefixed form, * is supported by the browser. * * ```js * testAllProps('boxSizing') // true * ``` * * It can optionally be given a CSS value in string form to test if a property * value is valid * * ```js * testAllProps('display', 'block') // true * testAllProps('display', 'penguin') // false * ``` * * A boolean can be passed as a third parameter to skip the value check when * native detection (@supports) isn't available. * * ```js * testAllProps('shapeOutside', 'content-box', true); * ``` */ function testAllProps(prop, value, skipValueTest) { return testPropsAll(prop, undefined, undefined, value, skipValueTest); } ModernizrProto.testAllProps = testAllProps; /*! { "name": "CSS Animations", "property": "cssanimations", "caniuse": "css-animation", "polyfills": ["transformie", "csssandpaper"], "tags": ["css"], "warnings": ["Android < 4 will pass this test, but can only animate a single property at a time"], "notes": [{ "name" : "Article: 'Dispelling the Android CSS animation myths'", "href": "https://goo.gl/OGw5Gm" }] } !*/ /* DOC Detects whether or not elements can be animated using CSS */ Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true)); /*! { "name": "Flexbox", "property": "flexbox", "caniuse": "flexbox", "tags": ["css"], "notes": [{ "name": "The _new_ flexbox", "href": "http://dev.w3.org/csswg/css3-flexbox" }], "warnings": [ "A `true` result for this detect does not imply that the `flex-wrap` property is supported; see the `flexwrap` detect." ] } !*/ /* DOC Detects support for the Flexible Box Layout model, a.k.a. Flexbox, which allows easy manipulation of layout order and sizing within a container. */ Modernizr.addTest('flexbox', testAllProps('flexBasis', '1px', true)); /*! { "name": "CSS Transforms", "property": "csstransforms", "caniuse": "transforms2d", "tags": ["css"] } !*/ Modernizr.addTest('csstransforms', function() { // Android < 3.0 is buggy, so we sniff and blacklist // http://git.io/hHzL7w return navigator.userAgent.indexOf('Android 2.') === -1 && testAllProps('transform', 'scale(1)', true); }); /*! { "name": "CSS Transitions", "property": "csstransitions", "caniuse": "css-transitions", "tags": ["css"] } !*/ Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true)); // Run each test testRunner(); delete ModernizrProto.addTest; delete ModernizrProto.addAsyncTest; // Run the things that are supposed to run after the tests for (var i = 0; i < Modernizr._q.length; i++) { Modernizr._q[i](); } // Leak Modernizr namespace window.Modernizr = Modernizr; ; })(window, document); ================================================ FILE: portiaui/vendor/mutation-summary.js ================================================ // Copyright 2011 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. var __extends = this.__extends || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } __.prototype = b.prototype; d.prototype = new __(); }; var MutationObserverCtor; if (typeof WebKitMutationObserver !== 'undefined') MutationObserverCtor = WebKitMutationObserver; else MutationObserverCtor = MutationObserver; if (MutationObserverCtor === undefined) { console.error('DOM Mutation Observers are required.'); console.error('https://developer.mozilla.org/en-US/docs/DOM/MutationObserver'); throw Error('DOM Mutation Observers are required'); } var NodeMap = (function () { function NodeMap() { this.nodes = []; this.values = []; } NodeMap.prototype.isIndex = function (s) { return +s === s >>> 0; }; NodeMap.prototype.nodeId = function (node) { var id = node[NodeMap.ID_PROP]; if (!id) id = node[NodeMap.ID_PROP] = NodeMap.nextId_++; return id; }; NodeMap.prototype.set = function (node, value) { var id = this.nodeId(node); this.nodes[id] = node; this.values[id] = value; }; NodeMap.prototype.get = function (node) { var id = this.nodeId(node); return this.values[id]; }; NodeMap.prototype.has = function (node) { return this.nodeId(node) in this.nodes; }; NodeMap.prototype.delete = function (node) { var id = this.nodeId(node); delete this.nodes[id]; this.values[id] = undefined; }; NodeMap.prototype.keys = function () { var nodes = []; for (var id in this.nodes) { if (!this.isIndex(id)) continue; nodes.push(this.nodes[id]); } return nodes; }; NodeMap.ID_PROP = '__mutation_summary_node_map_id__'; NodeMap.nextId_ = 1; return NodeMap; })(); function NodeIdMap(){ NodeMap.call(this); this.byId = {}; // Id -> Node } NodeIdMap.prototype = new NodeMap(); NodeIdMap.prototype.delete = function(node) { var id = this.get(node); if(id){ NodeMap.prototype.delete.call(this, node); delete this.byId[id]; } }; NodeIdMap.prototype.set = function(node, id) { NodeMap.prototype.set.call(this, node, id); this.byId[id] = node; }; /** * var reachableMatchableProduct = [ * // STAYED_OUT, ENTERED, STAYED_IN, EXITED * [ STAYED_OUT, STAYED_OUT, STAYED_OUT, STAYED_OUT ], // STAYED_OUT * [ STAYED_OUT, ENTERED, ENTERED, STAYED_OUT ], // ENTERED * [ STAYED_OUT, ENTERED, STAYED_IN, EXITED ], // STAYED_IN * [ STAYED_OUT, STAYED_OUT, EXITED, EXITED ] // EXITED * ]; */ var Movement; (function (Movement) { Movement[Movement["STAYED_OUT"] = 0] = "STAYED_OUT"; Movement[Movement["ENTERED"] = 1] = "ENTERED"; Movement[Movement["STAYED_IN"] = 2] = "STAYED_IN"; Movement[Movement["REPARENTED"] = 3] = "REPARENTED"; Movement[Movement["REORDERED"] = 4] = "REORDERED"; Movement[Movement["EXITED"] = 5] = "EXITED"; })(Movement || (Movement = {})); function enteredOrExited(changeType) { return changeType === 1 /* ENTERED */ || changeType === 5 /* EXITED */; } var NodeChange = (function () { function NodeChange(node, childList, attributes, characterData, oldParentNode, added, attributeOldValues, characterDataOldValue) { if (typeof childList === "undefined") { childList = false; } if (typeof attributes === "undefined") { attributes = false; } if (typeof characterData === "undefined") { characterData = false; } if (typeof oldParentNode === "undefined") { oldParentNode = null; } if (typeof added === "undefined") { added = false; } if (typeof attributeOldValues === "undefined") { attributeOldValues = null; } if (typeof characterDataOldValue === "undefined") { characterDataOldValue = null; } this.node = node; this.childList = childList; this.attributes = attributes; this.characterData = characterData; this.oldParentNode = oldParentNode; this.added = added; this.attributeOldValues = attributeOldValues; this.characterDataOldValue = characterDataOldValue; this.isCaseInsensitive = this.node.nodeType === Node.ELEMENT_NODE && this.node instanceof HTMLElement && this.node.ownerDocument instanceof HTMLDocument; } NodeChange.prototype.getAttributeOldValue = function (name) { if (!this.attributeOldValues) return undefined; if (this.isCaseInsensitive) name = name.toLowerCase(); return this.attributeOldValues[name]; }; NodeChange.prototype.getAttributeNamesMutated = function () { var names = []; if (!this.attributeOldValues) return names; for (var name in this.attributeOldValues) { names.push(name); } return names; }; NodeChange.prototype.attributeMutated = function (name, oldValue) { this.attributes = true; this.attributeOldValues = this.attributeOldValues || {}; if (name in this.attributeOldValues) return; this.attributeOldValues[name] = oldValue; }; NodeChange.prototype.characterDataMutated = function (oldValue) { if (this.characterData) return; this.characterData = true; this.characterDataOldValue = oldValue; }; // Note: is it possible to receive a removal followed by a removal. This // can occur if the removed node is added to an non-observed node, that // node is added to the observed area, and then the node removed from // it. NodeChange.prototype.removedFromParent = function (parent) { this.childList = true; if (this.added || this.oldParentNode) this.added = false; else this.oldParentNode = parent; }; NodeChange.prototype.insertedIntoParent = function () { this.childList = true; this.added = true; }; // An node's oldParent is // -its present parent, if its parentNode was not changed. // -null if the first thing that happened to it was an add. // -the node it was removed from if the first thing that happened to it // was a remove. NodeChange.prototype.getOldParent = function () { if (this.childList) { if (this.oldParentNode) return this.oldParentNode; if (this.added) return null; } return this.node.parentNode; }; return NodeChange; })(); var ChildListChange = (function () { function ChildListChange() { this.added = new NodeMap(); this.removed = new NodeMap(); this.maybeMoved = new NodeMap(); this.oldPrevious = new NodeMap(); this.moved = undefined; } return ChildListChange; })(); var TreeChanges = (function (_super) { __extends(TreeChanges, _super); function TreeChanges(rootNode, mutations) { _super.call(this); this.rootNode = rootNode; this.reachableCache = undefined; this.wasReachableCache = undefined; this.anyParentsChanged = false; this.anyAttributesChanged = false; this.anyCharacterDataChanged = false; for (var m = 0; m < mutations.length; m++) { var mutation = mutations[m]; switch (mutation.type) { case 'childList': this.anyParentsChanged = true; for (var i = 0; i < mutation.removedNodes.length; i++) { var node = mutation.removedNodes[i]; this.getChange(node).removedFromParent(mutation.target); } for (var i = 0; i < mutation.addedNodes.length; i++) { var node = mutation.addedNodes[i]; this.getChange(node).insertedIntoParent(); } break; case 'attributes': this.anyAttributesChanged = true; var change = this.getChange(mutation.target); change.attributeMutated(mutation.attributeName, mutation.oldValue); break; case 'characterData': this.anyCharacterDataChanged = true; var change = this.getChange(mutation.target); change.characterDataMutated(mutation.oldValue); break; } } } TreeChanges.prototype.getChange = function (node) { var change = this.get(node); if (!change) { change = new NodeChange(node); this.set(node, change); } return change; }; TreeChanges.prototype.getOldParent = function (node) { var change = this.get(node); return change ? change.getOldParent() : node.parentNode; }; TreeChanges.prototype.getIsReachable = function (node) { if (node === this.rootNode) return true; if (!node) return false; this.reachableCache = this.reachableCache || new NodeMap(); var isReachable = this.reachableCache.get(node); if (isReachable === undefined) { isReachable = this.getIsReachable(node.parentNode); this.reachableCache.set(node, isReachable); } return isReachable; }; // A node wasReachable if its oldParent wasReachable. TreeChanges.prototype.getWasReachable = function (node) { if (node === this.rootNode) return true; if (!node) return false; this.wasReachableCache = this.wasReachableCache || new NodeMap(); var wasReachable = this.wasReachableCache.get(node); if (wasReachable === undefined) { wasReachable = this.getWasReachable(this.getOldParent(node)); this.wasReachableCache.set(node, wasReachable); } return wasReachable; }; TreeChanges.prototype.reachabilityChange = function (node) { if (this.getIsReachable(node)) { return this.getWasReachable(node) ? 2 /* STAYED_IN */ : 1 /* ENTERED */; } return this.getWasReachable(node) ? 5 /* EXITED */ : 0 /* STAYED_OUT */; }; return TreeChanges; })(NodeMap); var MutationProjection = (function () { // TOOD(any) function MutationProjection(rootNode, mutations, selectors, calcReordered, calcOldPreviousSibling) { this.rootNode = rootNode; this.mutations = mutations; this.selectors = selectors; this.calcReordered = calcReordered; this.calcOldPreviousSibling = calcOldPreviousSibling; this.treeChanges = new TreeChanges(rootNode, mutations); this.entered = []; this.exited = []; this.stayedIn = new NodeMap(); this.visited = new NodeMap(); this.childListChangeMap = undefined; this.characterDataOnly = undefined; this.matchCache = undefined; this.processMutations(); } MutationProjection.prototype.processMutations = function () { if (!this.treeChanges.anyParentsChanged && !this.treeChanges.anyAttributesChanged) return; var changedNodes = this.treeChanges.keys(); for (var i = 0; i < changedNodes.length; i++) { this.visitNode(changedNodes[i], undefined); } }; MutationProjection.prototype.visitNode = function (node, parentReachable) { if (this.visited.has(node)) return; this.visited.set(node, true); var change = this.treeChanges.get(node); var reachable = parentReachable; // node inherits its parent's reachability change unless // its parentNode was mutated. if ((change && change.childList) || reachable == undefined) reachable = this.treeChanges.reachabilityChange(node); if (reachable === 0 /* STAYED_OUT */) return; // Cache match results for sub-patterns. this.matchabilityChange(node); if (reachable === 1 /* ENTERED */) { this.entered.push(node); } else if (reachable === 5 /* EXITED */) { this.exited.push(node); this.ensureHasOldPreviousSiblingIfNeeded(node); } else if (reachable === 2 /* STAYED_IN */) { var movement = 2 /* STAYED_IN */; if (change && change.childList) { if (change.oldParentNode !== node.parentNode) { movement = 3 /* REPARENTED */; this.ensureHasOldPreviousSiblingIfNeeded(node); } else if (this.calcReordered && this.wasReordered(node)) { movement = 4 /* REORDERED */; } } this.stayedIn.set(node, movement); } if (reachable === 2 /* STAYED_IN */) return; for (var child = node.firstChild; child; child = child.nextSibling) { this.visitNode(child, reachable); } }; MutationProjection.prototype.ensureHasOldPreviousSiblingIfNeeded = function (node) { if (!this.calcOldPreviousSibling) return; this.processChildlistChanges(); var parentNode = node.parentNode; var nodeChange = this.treeChanges.get(node); if (nodeChange && nodeChange.oldParentNode) parentNode = nodeChange.oldParentNode; var change = this.childListChangeMap.get(parentNode); if (!change) { change = new ChildListChange(); this.childListChangeMap.set(parentNode, change); } if (!change.oldPrevious.has(node)) { change.oldPrevious.set(node, node.previousSibling); } }; MutationProjection.prototype.getChanged = function (summary, selectors, characterDataOnly) { this.selectors = selectors; this.characterDataOnly = characterDataOnly; for (var i = 0; i < this.entered.length; i++) { var node = this.entered[i]; var matchable = this.matchabilityChange(node); if (matchable === 1 /* ENTERED */ || matchable === 2 /* STAYED_IN */) summary.added.push(node); } var stayedInNodes = this.stayedIn.keys(); for (var i = 0; i < stayedInNodes.length; i++) { var node = stayedInNodes[i]; var matchable = this.matchabilityChange(node); if (matchable === 1 /* ENTERED */) { summary.added.push(node); } else if (matchable === 5 /* EXITED */) { summary.removed.push(node); } else if (matchable === 2 /* STAYED_IN */ && (summary.reparented || summary.reordered)) { var movement = this.stayedIn.get(node); if (summary.reparented && movement === 3 /* REPARENTED */) summary.reparented.push(node); else if (summary.reordered && movement === 4 /* REORDERED */) summary.reordered.push(node); } } for (var i = 0; i < this.exited.length; i++) { var node = this.exited[i]; var matchable = this.matchabilityChange(node); if (matchable === 5 /* EXITED */ || matchable === 2 /* STAYED_IN */) summary.removed.push(node); } }; MutationProjection.prototype.getOldParentNode = function (node) { var change = this.treeChanges.get(node); if (change && change.childList) return change.oldParentNode ? change.oldParentNode : null; var reachabilityChange = this.treeChanges.reachabilityChange(node); if (reachabilityChange === 0 /* STAYED_OUT */ || reachabilityChange === 1 /* ENTERED */) throw Error('getOldParentNode requested on invalid node.'); return node.parentNode; }; MutationProjection.prototype.getOldPreviousSibling = function (node) { var parentNode = node.parentNode; var nodeChange = this.treeChanges.get(node); if (nodeChange && nodeChange.oldParentNode) parentNode = nodeChange.oldParentNode; var change = this.childListChangeMap.get(parentNode); if (!change) throw Error('getOldPreviousSibling requested on invalid node.'); return change.oldPrevious.get(node); }; MutationProjection.prototype.getOldAttribute = function (element, attrName) { var change = this.treeChanges.get(element); if (!change || !change.attributes) throw Error('getOldAttribute requested on invalid node.'); var value = change.getAttributeOldValue(attrName); if (value === undefined) throw Error('getOldAttribute requested for unchanged attribute name.'); return value; }; MutationProjection.prototype.attributeChangedNodes = function (includeAttributes) { if (!this.treeChanges.anyAttributesChanged) return {}; var attributeFilter; var caseInsensitiveFilter; if (includeAttributes) { attributeFilter = {}; caseInsensitiveFilter = {}; for (var i = 0; i < includeAttributes.length; i++) { var attrName = includeAttributes[i]; attributeFilter[attrName] = true; caseInsensitiveFilter[attrName.toLowerCase()] = attrName; } } var result = {}; var nodes = this.treeChanges.keys(); for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; var change = this.treeChanges.get(node); if (!change.attributes) continue; if (2 /* STAYED_IN */ !== this.treeChanges.reachabilityChange(node) || 2 /* STAYED_IN */ !== this.matchabilityChange(node)) { continue; } var element = node; var changedAttrNames = change.getAttributeNamesMutated(); for (var j = 0; j < changedAttrNames.length; j++) { var attrName = changedAttrNames[j]; if (attributeFilter && !attributeFilter[attrName] && !(change.isCaseInsensitive && caseInsensitiveFilter[attrName])) { continue; } var oldValue = change.getAttributeOldValue(attrName); if (oldValue === element.getAttribute(attrName)) continue; if (caseInsensitiveFilter && change.isCaseInsensitive) attrName = caseInsensitiveFilter[attrName]; result[attrName] = result[attrName] || []; result[attrName].push(element); } } return result; }; MutationProjection.prototype.getOldCharacterData = function (node) { var change = this.treeChanges.get(node); if (!change || !change.characterData) throw Error('getOldCharacterData requested on invalid node.'); return change.characterDataOldValue; }; MutationProjection.prototype.getCharacterDataChanged = function () { if (!this.treeChanges.anyCharacterDataChanged) return []; var nodes = this.treeChanges.keys(); var result = []; for (var i = 0; i < nodes.length; i++) { var target = nodes[i]; if (2 /* STAYED_IN */ !== this.treeChanges.reachabilityChange(target)) continue; var change = this.treeChanges.get(target); if (!change.characterData || target.textContent == change.characterDataOldValue) continue; result.push(target); } return result; }; MutationProjection.prototype.computeMatchabilityChange = function (selector, el) { if (!this.matchCache) this.matchCache = []; if (!this.matchCache[selector.uid]) this.matchCache[selector.uid] = new NodeMap(); var cache = this.matchCache[selector.uid]; var result = cache.get(el); if (result === undefined) { result = selector.matchabilityChange(el, this.treeChanges.get(el)); cache.set(el, result); } return result; }; MutationProjection.prototype.matchabilityChange = function (node) { var _this = this; // TODO(rafaelw): Include PI, CDATA? // Only include text nodes. if (this.characterDataOnly) { switch (node.nodeType) { case Node.COMMENT_NODE: case Node.TEXT_NODE: return 2 /* STAYED_IN */; default: return 0 /* STAYED_OUT */; } } // No element filter. Include all nodes. if (!this.selectors) return 2 /* STAYED_IN */; // Element filter. Exclude non-elements. if (node.nodeType !== Node.ELEMENT_NODE) return 0 /* STAYED_OUT */; var el = node; var matchChanges = this.selectors.map(function (selector) { return _this.computeMatchabilityChange(selector, el); }); var accum = 0 /* STAYED_OUT */; var i = 0; while (accum !== 2 /* STAYED_IN */ && i < matchChanges.length) { switch (matchChanges[i]) { case 2 /* STAYED_IN */: accum = 2 /* STAYED_IN */; break; case 1 /* ENTERED */: if (accum === 5 /* EXITED */) accum = 2 /* STAYED_IN */; else accum = 1 /* ENTERED */; break; case 5 /* EXITED */: if (accum === 1 /* ENTERED */) accum = 2 /* STAYED_IN */; else accum = 5 /* EXITED */; break; } i++; } return accum; }; MutationProjection.prototype.getChildlistChange = function (el) { var change = this.childListChangeMap.get(el); if (!change) { change = new ChildListChange(); this.childListChangeMap.set(el, change); } return change; }; MutationProjection.prototype.processChildlistChanges = function () { if (this.childListChangeMap) return; this.childListChangeMap = new NodeMap(); for (var i = 0; i < this.mutations.length; i++) { var mutation = this.mutations[i]; if (mutation.type != 'childList') continue; if (this.treeChanges.reachabilityChange(mutation.target) !== 2 /* STAYED_IN */ && !this.calcOldPreviousSibling) continue; var change = this.getChildlistChange(mutation.target); var oldPrevious = mutation.previousSibling; function recordOldPrevious(node, previous) { if (!node || change.oldPrevious.has(node) || change.added.has(node) || change.maybeMoved.has(node)) return; if (previous && (change.added.has(previous) || change.maybeMoved.has(previous))) return; change.oldPrevious.set(node, previous); } for (var j = 0; j < mutation.removedNodes.length; j++) { var node = mutation.removedNodes[j]; recordOldPrevious(node, oldPrevious); if (change.added.has(node)) { change.added.delete(node); } else { change.removed.set(node, true); change.maybeMoved.delete(node); } oldPrevious = node; } recordOldPrevious(mutation.nextSibling, oldPrevious); for (var j = 0; j < mutation.addedNodes.length; j++) { var node = mutation.addedNodes[j]; if (change.removed.has(node)) { change.removed.delete(node); change.maybeMoved.set(node, true); } else { change.added.set(node, true); } } } }; MutationProjection.prototype.wasReordered = function (node) { if (!this.treeChanges.anyParentsChanged) return false; this.processChildlistChanges(); var parentNode = node.parentNode; var nodeChange = this.treeChanges.get(node); if (nodeChange && nodeChange.oldParentNode) parentNode = nodeChange.oldParentNode; var change = this.childListChangeMap.get(parentNode); if (!change) return false; if (change.moved) return change.moved.get(node); change.moved = new NodeMap(); var pendingMoveDecision = new NodeMap(); function isMoved(node) { if (!node) return false; if (!change.maybeMoved.has(node)) return false; var didMove = change.moved.get(node); if (didMove !== undefined) return didMove; if (pendingMoveDecision.has(node)) { didMove = true; } else { pendingMoveDecision.set(node, true); didMove = getPrevious(node) !== getOldPrevious(node); } if (pendingMoveDecision.has(node)) { pendingMoveDecision.delete(node); change.moved.set(node, didMove); } else { didMove = change.moved.get(node); } return didMove; } var oldPreviousCache = new NodeMap(); function getOldPrevious(node) { var oldPrevious = oldPreviousCache.get(node); if (oldPrevious !== undefined) return oldPrevious; oldPrevious = change.oldPrevious.get(node); while (oldPrevious && (change.removed.has(oldPrevious) || isMoved(oldPrevious))) { oldPrevious = getOldPrevious(oldPrevious); } if (oldPrevious === undefined) oldPrevious = node.previousSibling; oldPreviousCache.set(node, oldPrevious); return oldPrevious; } var previousCache = new NodeMap(); function getPrevious(node) { if (previousCache.has(node)) return previousCache.get(node); var previous = node.previousSibling; while (previous && (change.added.has(previous) || isMoved(previous))) previous = previous.previousSibling; previousCache.set(node, previous); return previous; } change.maybeMoved.keys().forEach(isMoved); return change.moved.get(node); }; return MutationProjection; })(); var Summary = (function () { function Summary(projection, query) { var _this = this; this.projection = projection; this.added = []; this.removed = []; this.reparented = query.all || query.element ? [] : undefined; this.reordered = query.all ? [] : undefined; projection.getChanged(this, query.elementFilter, query.characterData); if (query.all || query.attribute || query.attributeList) { var filter = query.attribute ? [query.attribute] : query.attributeList; var attributeChanged = projection.attributeChangedNodes(filter); if (query.attribute) { this.valueChanged = attributeChanged[query.attribute] || []; } else { this.attributeChanged = attributeChanged; if (query.attributeList) { query.attributeList.forEach(function (attrName) { if (!_this.attributeChanged.hasOwnProperty(attrName)) _this.attributeChanged[attrName] = []; }); } } } if (query.all || query.characterData) { var characterDataChanged = projection.getCharacterDataChanged(); if (query.characterData) this.valueChanged = characterDataChanged; else this.characterDataChanged = characterDataChanged; } if (this.reordered) this.getOldPreviousSibling = projection.getOldPreviousSibling.bind(projection); } Summary.prototype.getOldParentNode = function (node) { return this.projection.getOldParentNode(node); }; Summary.prototype.getOldAttribute = function (node, name) { return this.projection.getOldAttribute(node, name); }; Summary.prototype.getOldCharacterData = function (node) { return this.projection.getOldCharacterData(node); }; Summary.prototype.getOldPreviousSibling = function (node) { return this.projection.getOldPreviousSibling(node); }; return Summary; })(); // TODO(rafaelw): Allow ':' and '.' as valid name characters. var validNameInitialChar = /[a-zA-Z_]+/; var validNameNonInitialChar = /[a-zA-Z0-9_\-]+/; // TODO(rafaelw): Consider allowing backslash in the attrValue. // TODO(rafaelw): There's got a to be way to represent this state machine // more compactly??? function escapeQuotes(value) { return '"' + value.replace(/"/, '\\\"') + '"'; } var Qualifier = (function () { function Qualifier() { } Qualifier.prototype.matches = function (oldValue) { if (oldValue === null) return false; if (this.attrValue === undefined) return true; if (!this.contains) return this.attrValue == oldValue; var tokens = oldValue.split(' '); for (var i = 0; i < tokens.length; i++) { if (this.attrValue === tokens[i]) return true; } return false; }; Qualifier.prototype.toString = function () { if (this.attrName === 'class' && this.contains) return '.' + this.attrValue; if (this.attrName === 'id' && !this.contains) return '#' + this.attrValue; if (this.contains) return '[' + this.attrName + '~=' + escapeQuotes(this.attrValue) + ']'; if ('attrValue' in this) return '[' + this.attrName + '=' + escapeQuotes(this.attrValue) + ']'; return '[' + this.attrName + ']'; }; return Qualifier; })(); var Selector = (function () { function Selector() { this.uid = Selector.nextUid++; this.qualifiers = []; } Object.defineProperty(Selector.prototype, "caseInsensitiveTagName", { get: function () { return this.tagName.toUpperCase(); }, enumerable: true, configurable: true }); Object.defineProperty(Selector.prototype, "selectorString", { get: function () { return this.tagName + this.qualifiers.join(''); }, enumerable: true, configurable: true }); Selector.prototype.isMatching = function (el) { return el[Selector.matchesSelector](this.selectorString); }; Selector.prototype.wasMatching = function (el, change, isMatching) { if (!change || !change.attributes) return isMatching; var tagName = change.isCaseInsensitive ? this.caseInsensitiveTagName : this.tagName; if (tagName !== '*' && tagName !== el.tagName) return false; var attributeOldValues = []; var anyChanged = false; for (var i = 0; i < this.qualifiers.length; i++) { var qualifier = this.qualifiers[i]; var oldValue = change.getAttributeOldValue(qualifier.attrName); attributeOldValues.push(oldValue); anyChanged = anyChanged || (oldValue !== undefined); } if (!anyChanged) return isMatching; for (var i = 0; i < this.qualifiers.length; i++) { var qualifier = this.qualifiers[i]; var oldValue = attributeOldValues[i]; if (oldValue === undefined) oldValue = el.getAttribute(qualifier.attrName); if (!qualifier.matches(oldValue)) return false; } return true; }; Selector.prototype.matchabilityChange = function (el, change) { var isMatching = this.isMatching(el); if (isMatching) return this.wasMatching(el, change, isMatching) ? 2 /* STAYED_IN */ : 1 /* ENTERED */; else return this.wasMatching(el, change, isMatching) ? 5 /* EXITED */ : 0 /* STAYED_OUT */; }; Selector.parseSelectors = function (input) { var selectors = []; var currentSelector; var currentQualifier; function newSelector() { if (currentSelector) { if (currentQualifier) { currentSelector.qualifiers.push(currentQualifier); currentQualifier = undefined; } selectors.push(currentSelector); } currentSelector = new Selector(); } function newQualifier() { if (currentQualifier) currentSelector.qualifiers.push(currentQualifier); currentQualifier = new Qualifier(); } var WHITESPACE = /\s/; var valueQuoteChar; var SYNTAX_ERROR = 'Invalid or unsupported selector syntax.'; var SELECTOR = 1; var TAG_NAME = 2; var QUALIFIER = 3; var QUALIFIER_NAME_FIRST_CHAR = 4; var QUALIFIER_NAME = 5; var ATTR_NAME_FIRST_CHAR = 6; var ATTR_NAME = 7; var EQUIV_OR_ATTR_QUAL_END = 8; var EQUAL = 9; var ATTR_QUAL_END = 10; var VALUE_FIRST_CHAR = 11; var VALUE = 12; var QUOTED_VALUE = 13; var SELECTOR_SEPARATOR = 14; var state = SELECTOR; var i = 0; while (i < input.length) { var c = input[i++]; switch (state) { case SELECTOR: if (c.match(validNameInitialChar)) { newSelector(); currentSelector.tagName = c; state = TAG_NAME; break; } if (c == '*') { newSelector(); currentSelector.tagName = '*'; state = QUALIFIER; break; } if (c == '.') { newSelector(); newQualifier(); currentSelector.tagName = '*'; currentQualifier.attrName = 'class'; currentQualifier.contains = true; state = QUALIFIER_NAME_FIRST_CHAR; break; } if (c == '#') { newSelector(); newQualifier(); currentSelector.tagName = '*'; currentQualifier.attrName = 'id'; state = QUALIFIER_NAME_FIRST_CHAR; break; } if (c == '[') { newSelector(); newQualifier(); currentSelector.tagName = '*'; currentQualifier.attrName = ''; state = ATTR_NAME_FIRST_CHAR; break; } if (c.match(WHITESPACE)) break; throw Error(SYNTAX_ERROR); case TAG_NAME: if (c.match(validNameNonInitialChar)) { currentSelector.tagName += c; break; } if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; currentQualifier.contains = true; state = QUALIFIER_NAME_FIRST_CHAR; break; } if (c == '#') { newQualifier(); currentQualifier.attrName = 'id'; state = QUALIFIER_NAME_FIRST_CHAR; break; } if (c == '[') { newQualifier(); currentQualifier.attrName = ''; state = ATTR_NAME_FIRST_CHAR; break; } if (c.match(WHITESPACE)) { state = SELECTOR_SEPARATOR; break; } if (c == ',') { state = SELECTOR; break; } throw Error(SYNTAX_ERROR); case QUALIFIER: if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; currentQualifier.contains = true; state = QUALIFIER_NAME_FIRST_CHAR; break; } if (c == '#') { newQualifier(); currentQualifier.attrName = 'id'; state = QUALIFIER_NAME_FIRST_CHAR; break; } if (c == '[') { newQualifier(); currentQualifier.attrName = ''; state = ATTR_NAME_FIRST_CHAR; break; } if (c.match(WHITESPACE)) { state = SELECTOR_SEPARATOR; break; } if (c == ',') { state = SELECTOR; break; } throw Error(SYNTAX_ERROR); case QUALIFIER_NAME_FIRST_CHAR: if (c.match(validNameInitialChar)) { currentQualifier.attrValue = c; state = QUALIFIER_NAME; break; } throw Error(SYNTAX_ERROR); case QUALIFIER_NAME: if (c.match(validNameNonInitialChar)) { currentQualifier.attrValue += c; break; } if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; currentQualifier.contains = true; state = QUALIFIER_NAME_FIRST_CHAR; break; } if (c == '#') { newQualifier(); currentQualifier.attrName = 'id'; state = QUALIFIER_NAME_FIRST_CHAR; break; } if (c == '[') { newQualifier(); state = ATTR_NAME_FIRST_CHAR; break; } if (c.match(WHITESPACE)) { state = SELECTOR_SEPARATOR; break; } if (c == ',') { state = SELECTOR; break; } throw Error(SYNTAX_ERROR); case ATTR_NAME_FIRST_CHAR: if (c.match(validNameInitialChar)) { currentQualifier.attrName = c; state = ATTR_NAME; break; } if (c.match(WHITESPACE)) break; throw Error(SYNTAX_ERROR); case ATTR_NAME: if (c.match(validNameNonInitialChar)) { currentQualifier.attrName += c; break; } if (c.match(WHITESPACE)) { state = EQUIV_OR_ATTR_QUAL_END; break; } if (c == '~') { currentQualifier.contains = true; state = EQUAL; break; } if (c == '=') { currentQualifier.attrValue = ''; state = VALUE_FIRST_CHAR; break; } if (c == ']') { state = QUALIFIER; break; } throw Error(SYNTAX_ERROR); case EQUIV_OR_ATTR_QUAL_END: if (c == '~') { currentQualifier.contains = true; state = EQUAL; break; } if (c == '=') { currentQualifier.attrValue = ''; state = VALUE_FIRST_CHAR; break; } if (c == ']') { state = QUALIFIER; break; } if (c.match(WHITESPACE)) break; throw Error(SYNTAX_ERROR); case EQUAL: if (c == '=') { currentQualifier.attrValue = ''; state = VALUE_FIRST_CHAR; break; } throw Error(SYNTAX_ERROR); case ATTR_QUAL_END: if (c == ']') { state = QUALIFIER; break; } if (c.match(WHITESPACE)) break; throw Error(SYNTAX_ERROR); case VALUE_FIRST_CHAR: if (c.match(WHITESPACE)) break; if (c == '"' || c == "'") { valueQuoteChar = c; state = QUOTED_VALUE; break; } currentQualifier.attrValue += c; state = VALUE; break; case VALUE: if (c.match(WHITESPACE)) { state = ATTR_QUAL_END; break; } if (c == ']') { state = QUALIFIER; break; } if (c == "'" || c == '"') throw Error(SYNTAX_ERROR); currentQualifier.attrValue += c; break; case QUOTED_VALUE: if (c == valueQuoteChar) { state = ATTR_QUAL_END; break; } currentQualifier.attrValue += c; break; case SELECTOR_SEPARATOR: if (c.match(WHITESPACE)) break; if (c == ',') { state = SELECTOR; break; } throw Error(SYNTAX_ERROR); } } switch (state) { case SELECTOR: case TAG_NAME: case QUALIFIER: case QUALIFIER_NAME: case SELECTOR_SEPARATOR: // Valid end states. newSelector(); break; default: throw Error(SYNTAX_ERROR); } if (!selectors.length) throw Error(SYNTAX_ERROR); return selectors; }; Selector.nextUid = 1; Selector.matchesSelector = (function () { var element = document.createElement('div'); if (typeof element['webkitMatchesSelector'] === 'function') return 'webkitMatchesSelector'; if (typeof element['mozMatchesSelector'] === 'function') return 'mozMatchesSelector'; if (typeof element['msMatchesSelector'] === 'function') return 'msMatchesSelector'; return 'matchesSelector'; })(); return Selector; })(); var attributeFilterPattern = /^([a-zA-Z:_]+[a-zA-Z0-9_\-:\.]*)$/; function validateAttribute(attribute) { if (typeof attribute != 'string') throw Error('Invalid request opion. attribute must be a non-zero length string.'); attribute = attribute.trim(); if (!attribute) throw Error('Invalid request opion. attribute must be a non-zero length string.'); if (!attribute.match(attributeFilterPattern)) throw Error('Invalid request option. invalid attribute name: ' + attribute); return attribute; } function validateElementAttributes(attribs) { if (!attribs.trim().length) throw Error('Invalid request option: elementAttributes must contain at least one attribute.'); var lowerAttributes = {}; var attributes = {}; var tokens = attribs.split(/\s+/); for (var i = 0; i < tokens.length; i++) { var name = tokens[i]; if (!name) continue; var name = validateAttribute(name); var nameLower = name.toLowerCase(); if (lowerAttributes[nameLower]) throw Error('Invalid request option: observing multiple case variations of the same attribute is not supported.'); attributes[name] = true; lowerAttributes[nameLower] = true; } return Object.keys(attributes); } function elementFilterAttributes(selectors) { var attributes = {}; selectors.forEach(function (selector) { selector.qualifiers.forEach(function (qualifier) { attributes[qualifier.attrName] = true; }); }); return Object.keys(attributes); } var MutationSummary = (function () { function MutationSummary(opts) { var _this = this; this.connected = false; this.options = MutationSummary.validateOptions(opts); this.observerOptions = MutationSummary.createObserverOptions(this.options.queries); this.root = this.options.rootNode; this.callback = this.options.callback; this.elementFilter = Array.prototype.concat.apply([], this.options.queries.map(function (query) { return query.elementFilter ? query.elementFilter : []; })); if (!this.elementFilter.length) this.elementFilter = undefined; this.calcReordered = this.options.queries.some(function (query) { return query.all; }); this.queryValidators = []; // TODO(rafaelw): Shouldn't always define this. if (MutationSummary.createQueryValidator) { this.queryValidators = this.options.queries.map(function (query) { return MutationSummary.createQueryValidator(_this.root, query); }); } this.observer = new MutationObserverCtor(function (mutations) { _this.observerCallback(mutations); }); this.reconnect(); } MutationSummary.createObserverOptions = function (queries) { var observerOptions = { childList: true, subtree: true }; var attributeFilter; function observeAttributes(attributes) { if (observerOptions.attributes && !attributeFilter) return; observerOptions.attributes = true; observerOptions.attributeOldValue = true; if (!attributes) { // observe all. attributeFilter = undefined; return; } // add to observed. attributeFilter = attributeFilter || {}; attributes.forEach(function (attribute) { attributeFilter[attribute] = true; attributeFilter[attribute.toLowerCase()] = true; }); } queries.forEach(function (query) { if (query.characterData) { observerOptions.characterData = true; observerOptions.characterDataOldValue = true; return; } if (query.all) { observeAttributes(); observerOptions.characterData = true; observerOptions.characterDataOldValue = true; return; } if (query.attribute) { observeAttributes([query.attribute.trim()]); return; } var attributes = elementFilterAttributes(query.elementFilter).concat(query.attributeList || []); if (attributes.length) observeAttributes(attributes); }); if (attributeFilter) observerOptions.attributeFilter = Object.keys(attributeFilter); return observerOptions; }; MutationSummary.validateOptions = function (options) { for (var prop in options) { if (!(prop in MutationSummary.optionKeys)) throw Error('Invalid option: ' + prop); } if (typeof options.callback !== 'function') throw Error('Invalid options: callback is required and must be a function'); if (!options.queries || !options.queries.length) throw Error('Invalid options: queries must contain at least one query request object.'); var opts = { callback: options.callback, rootNode: options.rootNode || document, observeOwnChanges: !!options.observeOwnChanges, oldPreviousSibling: !!options.oldPreviousSibling, queries: [] }; for (var i = 0; i < options.queries.length; i++) { var request = options.queries[i]; // all if (request.all) { if (Object.keys(request).length > 1) throw Error('Invalid request option. all has no options.'); opts.queries.push({ all: true }); continue; } // attribute if ('attribute' in request) { var query = { attribute: validateAttribute(request.attribute) }; query.elementFilter = Selector.parseSelectors('*[' + query.attribute + ']'); if (Object.keys(request).length > 1) throw Error('Invalid request option. attribute has no options.'); opts.queries.push(query); continue; } // element if ('element' in request) { var requestOptionCount = Object.keys(request).length; var query = { element: request.element, elementFilter: Selector.parseSelectors(request.element) }; if (request.hasOwnProperty('elementAttributes')) { query.attributeList = validateElementAttributes(request.elementAttributes); requestOptionCount--; } if (requestOptionCount > 1) throw Error('Invalid request option. element only allows elementAttributes option.'); opts.queries.push(query); continue; } // characterData if (request.characterData) { if (Object.keys(request).length > 1) throw Error('Invalid request option. characterData has no options.'); opts.queries.push({ characterData: true }); continue; } throw Error('Invalid request option. Unknown query request.'); } return opts; }; MutationSummary.prototype.createSummaries = function (mutations) { if (!mutations || !mutations.length) return []; var projection = new MutationProjection(this.root, mutations, this.elementFilter, this.calcReordered, this.options.oldPreviousSibling); var summaries = []; for (var i = 0; i < this.options.queries.length; i++) { summaries.push(new Summary(projection, this.options.queries[i])); } return summaries; }; MutationSummary.prototype.checkpointQueryValidators = function () { this.queryValidators.forEach(function (validator) { if (validator) validator.recordPreviousState(); }); }; MutationSummary.prototype.runQueryValidators = function (summaries) { this.queryValidators.forEach(function (validator, index) { if (validator) validator.validate(summaries[index]); }); }; MutationSummary.prototype.changesToReport = function (summaries) { return summaries.some(function (summary) { var summaryProps = [ 'added', 'removed', 'reordered', 'reparented', 'valueChanged', 'characterDataChanged']; if (summaryProps.some(function (prop) { return summary[prop] && summary[prop].length; })) return true; if (summary.attributeChanged) { var attrNames = Object.keys(summary.attributeChanged); var attrsChanged = attrNames.some(function (attrName) { return !!summary.attributeChanged[attrName].length; }); if (attrsChanged) return true; } return false; }); }; MutationSummary.prototype.observerCallback = function (mutations) { if (!this.options.observeOwnChanges) this.observer.disconnect(); var summaries = this.createSummaries(mutations); this.runQueryValidators(summaries); if (this.options.observeOwnChanges) this.checkpointQueryValidators(); if (this.changesToReport(summaries)) this.callback(summaries); // disconnect() may have been called during the callback. if (!this.options.observeOwnChanges && this.connected) { this.checkpointQueryValidators(); this.observer.observe(this.root, this.observerOptions); } }; MutationSummary.prototype.reconnect = function () { if (this.connected) throw Error('Already connected'); this.observer.observe(this.root, this.observerOptions); this.connected = true; this.checkpointQueryValidators(); }; MutationSummary.prototype.takeSummaries = function () { if (!this.connected) throw Error('Not connected'); var summaries = this.createSummaries(this.observer.takeRecords()); return this.changesToReport(summaries) ? summaries : undefined; }; MutationSummary.prototype.disconnect = function () { var summaries = this.takeSummaries(); this.observer.disconnect(); this.connected = false; return summaries; }; MutationSummary.NodeMap = NodeMap; MutationSummary.NodeIdMap = NodeIdMap; MutationSummary.parseElementFilter = Selector.parseSelectors; MutationSummary.optionKeys = { 'callback': true, 'queries': true, 'rootNode': true, 'oldPreviousSibling': true, 'observeOwnChanges': true }; return MutationSummary; })(); ================================================ FILE: portiaui/vendor/tree-mirror.js ================================================ /// var TreeMirror = (function () { function TreeMirror(root, delegate) { this.root = root; this.delegate = delegate; this.idMap = {}; } TreeMirror.prototype.initialize = function (rootId, children, baseURI) { this.baseURI = baseURI; this.idMap[rootId] = this.root; for (var i = 0; i < children.length; i++) this.deserializeNode(children[i], this.root); }; TreeMirror.prototype.applyChanged = function (removed, addedOrMoved, attributes, text) { var _this = this; // NOTE: Applying the changes can result in an attempting to add a child // to a parent which is presently an ancestor of the parent. This can occur // based on random ordering of moves. The way we handle this is to first // remove all changed nodes from their parents, then apply. addedOrMoved.forEach(function (data) { var node = _this.deserializeNode(data); var parent = _this.deserializeNode(data.parentNode); var previous = _this.deserializeNode(data.previousSibling); if (node.parentNode) node.parentNode.removeChild(node); }); removed.forEach(function (data) { var node = _this.deserializeNode(data); if (node.parentNode) node.parentNode.removeChild(node); }); addedOrMoved.forEach(function (data) { var node = _this.deserializeNode(data); var parent = _this.deserializeNode(data.parentNode); var previous = _this.deserializeNode(data.previousSibling); parent.insertBefore(node, previous ? previous.nextSibling : parent.firstChild); }); attributes.forEach(function (data) { var node = _this.deserializeNode(data); Object.keys(data.attributes).forEach(function (attrName) { var newVal = data.attributes[attrName]; if (newVal === null) { node.removeAttribute(attrName); } else { if (!_this.delegate || !_this.delegate.setAttribute || !_this.delegate.setAttribute(node, attrName, newVal)) { node.setAttribute(attrName, newVal); } } }); }); text.forEach(function (data) { var node = _this.deserializeNode(data); node.textContent = data.textContent; }); removed.forEach(function (node) { delete _this.idMap[node.id]; }); }; TreeMirror.prototype.deserializeNode = function (nodeData, parent) { var _this = this; if (nodeData === null) return null; var node = this.idMap[nodeData.id]; if (node) return node; var doc = this.root.ownerDocument; if (doc === null) doc = this.root; switch (nodeData.nodeType) { case Node.COMMENT_NODE: node = doc.createComment(nodeData.textContent); break; case Node.TEXT_NODE: node = doc.createTextNode(nodeData.textContent); break; case Node.DOCUMENT_TYPE_NODE: try { node = doc.implementation.createDocumentType(nodeData.name, nodeData.publicId, nodeData.systemId); } catch (e) { // Ignore error from incorrect document type } break; case Node.ELEMENT_NODE: if (this.delegate && this.delegate.createElement) node = this.delegate.createElement(nodeData.tagName); if (!node) node = doc.createElement(nodeData.tagName); node.setAttribute('data-tagid', nodeData.id); Object.keys(nodeData.attributes).forEach(function (name) { if (!_this.delegate || !_this.delegate.setAttribute || !_this.delegate.setAttribute(node, name, nodeData.attributes[name])) { node.setAttribute(name, nodeData.attributes[name]); } }); break; } if (!node) { throw new Error("No node with that id."); } this.idMap[nodeData.id] = node; node.nodeid = nodeData.id; if (parent) parent.appendChild(node); if (nodeData.childNodes) { for (var i = 0; i < nodeData.childNodes.length; i++) this.deserializeNode(nodeData.childNodes[i], node); } return node; }; return TreeMirror; })(); var URL_ATTRIBUTES = { img_src: true, link_href: true, input_src: true, body_background: true, table_background: true, td_background: true, tr_background: true, th_background: true, tbody_background: true, thead_background: true, tfoot_background: true, col_background: true, colgroup_background: true, section_background: true, head_profile: true, html_manifest: true, command_icon: true, embed_src: true, object_data: true, video_poster: true, form_action: true, iframe_src: true }; function isUrlAttribute(tagName, attribute) { var key = tagName.toLowerCase() + '_' + attribute.toLowerCase(); return URL_ATTRIBUTES[key] || false; } var TreeMirrorClient = (function () { function TreeMirrorClient(target, mirror, testingQueries) { var _this = this; this.target = target; this.mirror = mirror; this.nextId = 1; this.knownNodes = new MutationSummary.NodeIdMap(); //this.knownNodes = new MutationSummary.NodeMap(); var rootId = this.serializeNode(target).id; var children = []; for (var child = target.firstChild; child; child = child.nextSibling) children.push(this.serializeNode(child, true)); this.mirror.initialize(rootId, children, target.baseURI); var self = this; var queries = [{ all: true }]; if (testingQueries) queries = queries.concat(testingQueries); this.mutationSummary = new MutationSummary({ rootNode: target, callback: function (summaries) { try { _this.applyChanged(summaries); } catch (e) { if (e.message !== 'No node with that id') { throw e; } } }, queries: queries }); } TreeMirrorClient.prototype.disconnect = function () { if (this.mutationSummary) { this.mutationSummary.disconnect(); this.mutationSummary = undefined; } }; TreeMirrorClient.prototype.rememberNode = function (node) { var id = this.nextId++; this.knownNodes.set(node, id); return id; }; TreeMirrorClient.prototype.forgetNode = function (node) { this.knownNodes.delete(node); }; TreeMirrorClient.prototype.serializeAttribute = function (node, attr, obj) { var value = node.getAttribute(attr); var tagName = node.tagName; if(value === null) { obj[attr] = null; // Attribute was removed obj['data-portia-' + attr] = null; } else if(attr === "style"){ obj[attr] = __portiaApi.processCss(value, node.baseURI); obj['data-portia-' + attr] = value; } else if (attr === 'srcset' && tagName === 'IMG') { var split_attr = value.split(',') for (var i=0; i < split_attr.length; i++) { split_attr[i] = __portiaApi.wrapUrl( split_attr[i].trim(), node.baseURI); } obj[attr] = split_attr.join(', ') obj['data-portia-' + attr] = value; } else if (isUrlAttribute(tagName, attr)){ obj[attr] = __portiaApi.wrapUrl(value, node.baseURI); obj['data-portia-' + attr] = value; } else if (tagName === 'A' && attr === 'href') { value = node.href; if(!value || /^\s*javascript:/i.test(value)){ obj[attr] = 'javascript:void(0)'; obj['data-portia-' + attr] = value; } else { obj[attr] = value; } } else { obj[attr] = value; } }; TreeMirrorClient.prototype.serializeNode = function (node, recursive) { if (node === null) return null; var id = this.knownNodes.get(node); if (id !== undefined) { return { id: id }; } var data = { nodeType: node.nodeType, id: this.rememberNode(node) }; switch (data.nodeType) { case Node.DOCUMENT_TYPE_NODE: var docType = node; data.name = docType.name; data.publicId = docType.publicId; data.systemId = docType.systemId; break; case Node.COMMENT_NODE: case Node.TEXT_NODE: data.textContent = node.textContent; if(node.parentNode && node.parentNode.tagName == "STYLE"){ data.textContent = __portiaApi.processCss(data.textContent, node.baseURI); } break; case Node.ELEMENT_NODE: var elm = node; data.tagName = elm.tagName; data.attributes = {}; for (var i = 0; i < elm.attributes.length; i++) { var attr = elm.attributes[i]; this.serializeAttribute(node, attr.name, data.attributes); } if (recursive && elm.childNodes.length) { data.childNodes = []; for (var child = elm.firstChild; child; child = child.nextSibling) data.childNodes.push(this.serializeNode(child, true)); } break; } return data; }; TreeMirrorClient.prototype.serializeAddedAndMoved = function (added, reparented, reordered) { var _this = this; var all = added.concat(reparented).concat(reordered); var parentMap = new MutationSummary.NodeMap(); all.forEach(function (node) { var parent = node.parentNode; var children = parentMap.get(parent); if (!children) { children = new MutationSummary.NodeMap(); parentMap.set(parent, children); } children.set(node, true); }); var moved = []; parentMap.keys().forEach(function (parent) { var children = parentMap.get(parent); var keys = children.keys(); while (keys.length) { var node = keys[0]; while (node.previousSibling && children.has(node.previousSibling)) node = node.previousSibling; while (node && children.has(node)) { var data = _this.serializeNode(node); data.previousSibling = _this.serializeNode(node.previousSibling); data.parentNode = _this.serializeNode(node.parentNode); moved.push(data); children.delete(node); node = node.nextSibling; } var keys = children.keys(); } }); return moved; }; TreeMirrorClient.prototype.serializeAttributeChanges = function (attributeChanged) { var _this = this; var map = new MutationSummary.NodeMap(); Object.keys(attributeChanged).forEach(function (attrName) { (attributeChanged[attrName] || []).forEach(function (element) { var record = map.get(element); if (!record) { record = _this.serializeNode(element); record.attributes = {}; map.set(element, record); } _this.serializeAttribute(element, attrName, record.attributes); }); }); return map.keys().map(function (node) { return map.get(node); }); }; TreeMirrorClient.prototype.applyChanged = function (summaries) { var _this = this; var summary = summaries[0]; var removed = summary.removed.map(function (node) { return _this.serializeNode(node); }); var moved = this.serializeAddedAndMoved(summary.added, summary.reparented, summary.reordered); var attributes = this.serializeAttributeChanges(summary.attributeChanged); var text = summary.characterDataChanged.map(function (node) { var data = _this.serializeNode(node); data.textContent = node.textContent; return data; }); this.mirror.applyChanged(removed, moved, attributes, text); summary.removed.forEach(function (node) { _this.forgetNode(node); }); }; return TreeMirrorClient; })(); ================================================ FILE: slybot/.gitignore ================================================ *.pyc docs/_build slybot.egg-info/ ================================================ FILE: slybot/CHANGES ================================================ Slybot 0.13.3 Update slybot to work with python 3.7 and Scrapy 1.6 Slybot 0.13.2 Allow default spidermanager to load zipfiles Slybot 0.13.1 Choose parent of first extracted repeated item for parent region Drop empty fields if css extraction fails Handle requests through Splash in python 3 Slybot 0.13.0 Update slybot to use the most recent libraries Add a DropMetaPipeline to remove unwanted meta fields from items Allow `\r` character to be used in start url feeds Use `rendered_html` when building sample if JS enabled Limit CSS selector annotations to a single element Allow scrapy shell to find a spider if the name matches the url hostname Slybot 0.13.0b37 Do not create repeated extractor for CSS/XPath annotations Handle parsing Empty HTML response without raising error Handle malformed JSON annotation due to invalid HTML Merge fields extracted with the same name instead of deleting them Slybot 0.13.0b36 Fix python 3 compatibility Fix extraction from splash when using default script for `execute` endpoint Slybot 0.13.0b35 Cache selector searches for container to increase sample build speed Better handle XML responses Use extract endpoint for spiders using splash Store and load cookies when using splash Fix error when loading broken samples in Portia UI Fix bytes/unicode issue with regex extractor `__name__` Fix error thrown for missing annotation data in sample when finding schema Slybot 0.13.0b34 Fix error when building legacy spiders Slybot 0.13.0b33 Add serializer for datetime objects when they are being exported Handle malformed data when building selector Add chardet as slybot requirement Find element for container if it is missing Do not re-encode or decode binary or text data. Remove duplication by using Storage Abstraction for loading spiders. Slybot 0.13.0b32 Fix bug with url following Improve migration for spiders using tables Change spider loading to be lazy to improve performance when starting spider Do not replace named html entities in urls Use an empty collection of annotations if none found during migration Slybot 0.13.0b31 Do not require portia repo to build slybot distribution Slybot 0.13.0b30 Add legacy compile mode for samples Slybot 0.13.0b29 Allow arbitrary nesting Allow annotations and containers to share an element Slybot 0.13.0b28 Handle required fields from schemas in item processor Extract CSS and XPath in the SlybotIBLExtractor Run item validation in the SlybotIBLExtractor Fix nested items using item processor Add `annotated` flag to samples to avoid rebuilding samples Slybot 0.13.0b27 Remove tags from html content Extract raw html when using css selectors Fix unicode bug Handle invalid selectors gracefully Do not extract items with only meta fields and url Slybot 0.13.0b26 Fix issue with empty css selectors Change IblItem to be a subclass of scrapy.Item Slybot 0.13.0b25 Add configurable jump sizes and separators for repeated annotations Add ItemProcessor and selector handling to non repeated items Shorten specialised selectors when building sample if no elements found Clean up some tests Slybot 0.13.0b24 Add ability to extract CSS and XPath selectors as part of items Fix issue where base url is terminated by backslash Fix closing unclosed annotation tag during template parsing Slybot 0.13.0b23 Add FeedGenerator Slybot 0.13.0b22 Add Normalization for generated and normal urls Add body field to samples (used to decide is JS is used or not) Repair annotation ids if they have been truncated Repair missing fields in annotations Create deterministic id generator so fields can be "re-created" Save schemas after creating missing fields and schemas Handle missing extractors while porting samples Return `None, None` instead of `None` for error when finding element Fix bug in repeated field extractor Fix error when creating item with single repeated field Remove reverences to `accept_selectors` and `reject_selectors` Slybot 0.13.0b21 Improve repeated fields for slybot Extract repeated lists of values Container can only extract a single item unless it wraps a repeated container Better handle cases where not all repeated items have all fields Fixed printing error with BaseExtractor Removed legacy support (legacy now uses scrapely.InstanceBasedLearningExtractor) Log slybot version when using spidermanager Add samples to train page clustering on subsequest crawls Add samples to train page clustering on subsequest crawls Slybot 0.13.0b20 Allow slybot to be userd with scrapy<1.1.0 Slybot 0.13.0b19 Better template matching Update project url in setup.py Add missing dependency in setup.py Fix multiple containers in a single sample Fix dupefilter fallback to different schema error add annotated_body to sample if not present Slybot 0.13.0b18 Add selectors to annotation metadata. Fix extraction issue. Slybot 0.13.0b17 Selectors correctly generated in the presence of HTML comments Pagination link extractor now uses start_urls from spec to specify links to follow Corrected bug that manifested when extracting items with more than one sibling Slybot 0.13.0b16 Add trigger in spec for `page_finder` algorithm for extraction Fix bug where `None` can be passed to strip_url in image extractor Slybot 0.13.0b15 Add ability to adjust splash wait time Slybot 0.13.0b14 Fix per annotation requireds Fix problem with suffix when extracting final item Convert old style annotation to new style annotation when merging annotations Slybot 0.13.0b13 Change unicode to HtmlPageRegion when using type extractors Add schema for generated_urls Slybot 0.13.0b12 Merge annotations pointing to single element Slybot 0.13.0b11 Add start urls generation Fix per annotation requireds Fix illegal characters in urls Change speed test iterations using `SLYBOT_SPEED_TEST_ITERATIONS` env variable Refactor spider init Improve tests Slybot 0.13.0b10 Add extractors to descriptors Check for required fields using fields ids Allow `null` value for `allowed_domains` Slybot 0.13.0b9 Build all new samples when starting spider Do not throw error when fields are missing from item Slybot 0.13.0b8 Limit domains to template and start url hosts if `allowed_domains` is empty Do not drop items after first item if `version_fields` are empty Slybot 0.13.0b7 Create ScrapyItem correctly if no item found Slybot 0.13.0b6 Add `_type` field to ScrapyItem created from dict Slybot 0.13.0b5 Fallback for older projects Slybot 0.13.0b4 Fix off by one error for generated annotations. Process variant fields Slybot 0.13.0b3 Add legacy support for variants Slybot 0.13.0b2 Fix nested items structure. Use live page while annotating and stored page when building annotated_body Move migration code to slybot Slybot 0.13.0b1 Add Multiple item extraction. Add support for nested items. Add extractors backend. Add per annotation extractors rather than per field. Add support for annotation `selector` field when building annotated body. Add latest items and extractors when extracting data during annotation. Add variant extractors. Add pagination link extractor. Add support for atom, rss and xml sitemaps. Add algorithm for calculating containers and siblings. Add saving for page HTML when creating sample. Add ability to rename fields. Add backwards compatability to sample. Add selectors to existing annotations. Add pre and post text to generated annotations. Fix instantiate Annotations class. Fix issuse where default scrapely RecordExtractor fails. Port sample if it has a version less than 0.13.0. Strip whitespace from uris. Make htmlpage optional for type adapters. Use type extractors and adapters correctly. Change annotation format to allow extracting a single attribute to many fields. When loading template add annotation text to annotations with pre and post text. Loop over elements iterator rather than using map function. Add `all` option to `links_to_follow`. Save HTML and update annotations correctly. ================================================ FILE: slybot/MANIFEST.in ================================================ include README.rst include requirements.txt include slybot/validation/schemas.json include slybot/splash-script-combined.js ================================================ FILE: slybot/Makefile.buildbot ================================================ build: bin/makedeb ================================================ FILE: slybot/README.rst ================================================ ============== Slybot crawler ============== Slybot is a Python web crawler for doing web scraping. It's implemented on top of the `Scrapy`_ web crawling framework and the `Scrapely`_ extraction library. The documentation (including installation and usage) can be found at: http://slybot.readthedocs.org/ .. _Scrapely: https://github.com/scrapy/scrapely .. _Scrapy: http://scrapy.org ================================================ FILE: slybot/bin/makedeb ================================================ #!/bin/sh version=$(python setup.py --version)-r$(git log --oneline | wc -l)+$(date +%Y%m%d%H%M)~$(git rev-parse --short HEAD)${BUILD_CODE:+~$BUILD_CODE} debchange -m -D unstable --force-distribution -v $version "Automatic build" debuild --no-lintian -us -uc -b ================================================ FILE: slybot/bin/portiacrawl ================================================ #!/usr/bin/env python3 """Allow to easily run slybot spiders on console. If spider is not given, print a list of available spiders inside the project""" import os import subprocess from optparse import OptionParser def main(): parser = OptionParser(description=__doc__, usage="%prog [spider] [options]") parser.add_option("--settings", help="Give specific settings module (must be on python path)", default='slybot.settings') parser.add_option("--logfile", help="Specify log file") parser.add_option("-a", help="Add spider arguments", dest="spargs", action="append", default=[], metavar="NAME=VALUE") parser.add_option("-s", help="Add extra scrapy settings", dest="extra_settings", action="append", default=[], metavar="NAME=VALUE") parser.add_option("--output", "-o", help='dump scraped items into FILE (use - for stdout)', metavar='FILE') parser.add_option("--output-format", "-t", metavar='FORMAT', help='format to use for dumping items with -o (default: jsonlines)') parser.add_option("--verbose", "-v", action="store_true", default=False, help="more verbose") opts, args = parser.parse_args() try: project_specs = args[0] if not os.path.exists(project_specs) or len(args) > 2: parser.print_help() return except IndexError: parser.print_help() return if opts.settings: os.environ["SCRAPY_SETTINGS_MODULE"] = opts.settings command_spec = ["scrapy", "crawl", args[1]] if len(args) == 2 else ["scrapy", "list"] if project_specs.endswith(".zip"): command_spec.extend([ "-s", "PROJECT_DIR=%s" % project_specs, "-s", "SPIDER_MANAGER_CLASS=slybot.spidermanager.SlybotSpiderManager", ]) else: command_spec.extend([ "-s", "PROJECT_DIR=%s" % project_specs, "-s", "SPIDER_LOADER_CLASS=slybot.spidermanager.SlybotSpiderManager", ]) if opts.logfile: command_spec.append("--logfile=%s" % opts.logfile) if opts.output: command_spec.append("--output=%s" % opts.output) if opts.output_format: command_spec.append("--output-format=%s" % opts.output_format) for sparg in opts.spargs: command_spec.append("-a") command_spec.append(sparg) for setting in opts.extra_settings: command_spec.append("-s") command_spec.append(setting) if opts.verbose: print(" ".join(command_spec)) subprocess.call(command_spec) main() ================================================ FILE: slybot/bin/slybot ================================================ #!/usr/bin/env python3 import os os.environ['SCRAPY_SETTINGS_MODULE'] = 'slybot.settings' from scrapy.cmdline import execute execute() ================================================ FILE: slybot/debian/changelog ================================================ python-slybot (0.9) unstable; urgency=low * Initial release. -- Scrapinghub Team Wed, 31 Oct 2012 16:32:13 -0300 ================================================ FILE: slybot/debian/compat ================================================ 7 ================================================ FILE: slybot/debian/control ================================================ Source: python-slybot Section: python Priority: extra Maintainer: Scrapinghub Team Build-Depends: debhelper (>= 7), python (>=2.7) Standards-Version: 3.8.3 Homepage: https://github.com/scrapinghub/portia Package: python-slybot Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, scrapy (>= 1.0.3.post6), python-scrapely, python-loginform, python-lxml, python-dateparser, python-scrapy-splash, python-page-finder Description: A web crawler implemented in Python. Slybot is a Python web crawler for doing web scraping. It's implemented on top of the Scrapy web crawling framework and the Scrapely extraction library. ================================================ FILE: slybot/debian/copyright ================================================ Copyright (C) 2011-2012 Scrapinghub ================================================ FILE: slybot/debian/pyversions ================================================ 2.5- ================================================ FILE: slybot/debian/rules ================================================ #!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 %: dh $@ ================================================ FILE: slybot/docs/Makefile ================================================ # Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Slybot.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Slybot.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Slybot" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Slybot" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." htmlview: html python -c "import webbrowser; webbrowser.open('_build/html/index.html')" ================================================ FILE: slybot/docs/conf.py ================================================ # -*- coding: utf-8 -*- # # Slybot documentation build configuration file, created by # sphinx-quickstart on Thu Aug 22 10:19:15 2013. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Slybot' copyright = u'2013, Scrapy team' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '0.9' # The full version, including alpha/beta/rc tags. release = '0.9' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # 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 = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'Slybotdoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Slybot.tex', u'Slybot Documentation', u'Scrapy team', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'slybot', u'Slybot Documentation', [u'Scrapy team'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'Slybot', u'Slybot Documentation', u'Scrapy team', 'Slybot', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' ================================================ FILE: slybot/docs/index.rst ================================================ ============================== Slybot |version| documentation ============================== Slybot is a Python web crawler for doing web scraping. It's implemented on top of the `Scrapy`_ web crawling framework and the `Scrapely`_ extraction library. Requirements ============ * `Scrapy`_ * `Scrapely`_ * `loginform`_ * lxml Installation ============ To install the last development version:: pip install git+https://github.com/scrapy/slybot.git To install the last stable version:: pip install slybot Quick Usage =========== Create a directory called ``slybot-project``, place your slybot project (JSON files) there. To get a list of all spiders:: slybot list To run a specific specific spider:: slybot crawl For those familiar with Scrapy, ``slybot`` is a thin wrapper for the ``scrapy`` command, that just instructs Scrapy to use Slybot settings (``slybot.settings``). All commands and arguments supported by the ``scrapy`` command are also supported by the ``slybot`` command, although a few of them don't apply. Slybot projects =============== Slybot projects are configured through a collection of JSON files which are documented in :doc:`project`. Example project =============== There is a working slybot project example in `slybot/tests/data/SampleProject`_ that is used for tests and hence use most of the available features. User interfaces =============== Here is a list of known UIs to create Slybot templates: * `Scrapely tool`_ (command line interface) * `Scrapinghub Autoscraping`_ (visual, web-based) Advanced configuration ====================== Slybot is a `Scrapy`_ project, so it can be tuned and configured using `Scrapy settings`_. For more information see: :doc:`config`. Spiderlets ========== The behaviour of Slybot spiders can also be tuned with small (Python) code snippets called spiderlets. For more information see :doc:`spiderlets`. Table of contents ================= .. toctree:: :maxdepth: 2 project config spiderlets .. _Scrapy: https://github.com/scrapy/scrapy .. _Scrapely: https://github.com/scrapy/scrapely .. _loginform: https://github.com/scrapy/loginform .. _slybot/tests/data/SampleProject: https://github.com/scrapy/slybot/tree/master/slybot/tests/data/SampleProject .. _Scrapy settings: http://doc.scrapy.org/en/latest/topics/settings.html .. _Scrapely tool: https://github.com/scrapy/scrapely#usage-command-line-tool .. _Scrapinghub Autoscraping: http://scrapinghub.com/autoscraping.html ================================================ FILE: slybot/docs/make.bat ================================================ @ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Slybot.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Slybot.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end ================================================ FILE: slybot/docs/project.rst ================================================ ===================== Slybot project format ===================== This document describes the format used by slybot to store the configuration of a project and its spiders. * The format consists of a set of JSON files, laid out in a specific directory structure * All JSON files are encoded in UTF-8 format * Unless specified as "optional", all attributes are required Files and structure =================== The project consists of the following files and structure:: project.json items.json extractors.json fieldtypes.json spiders/ spider1.json spider2.json ... project.json ------------ A project object. items.json ---------- An items object. extractors.json --------------- A mapping from extractor ids to extractor objects. fieldtypes.json --------------- A mapping from field type name to field type objects. spiders/NAME.json ----------------- A spider object. Object types ============ Summary of object types: * `Project`_ * `Items`_ * `Item`_ * `Field`_ * `Field Type`_ * `Extractor`_ * `Template`_ * `Spider`_ * `Request`_ Project ------- The project object contains the global project metadata:: { "name": "Slybot Test Project", "version": "1.0", "comment": "" } Attributes: name : string The project name. version : string Version number of the format. comment : string : optional A comment provided by the user. Items ----- The items object contains all the item objects used in the project, it is represented as a mapping of item ids to items:: { "person": item object 1, "job": item object 2, ... } Item ---- An item object represents a individual object to be extracted by the system, i.e: person, job, category, etc.:: { fields: { "first_name": field object 1, "last_name": field object 2, } }, Attributes: display_name: string : optional User-friendly name of the item. If not specified, the item id will be used instead. fields : mapping This is a mapping of the field names to the field objects representing the properties of this item. Field ----- The field describes the properties of an item field:: { "type": "string", "required": "true", "vary": "true", }, Attributes: type : string The field type. It can reference a field type defined in `fieldtypes.json` or be one of the following built-in types: * safe html * url * text * image * geopoint * number * raw html * price required : boolean Whether the field is required to produce a successful match. All required fields must extract data, otherwise the extraction is considered to have failed and the data is discarded. vary : boolean Whether to ignore this field for duplicate detection. For example, sometimes the same product is available under many urls, in which case you would want to enable this attribute for the ``url`` field, if you want to drop duplicates. description : string : optional Field description. Field Type ---------- Attributes: extractor : string? The extractor used for this field type. TODO: define how to specify extractor. adaptor : string? The adaptor used for this field types. Unlike extractors, adaptors are applied after extraction has occurred and hence cannot affect the matching process. TODO: how to specify the adaptor (python func, etc). Spider ------ The Spider object is the top-level object that describes a slybot spider:: { "start_urls": list of strings, "allowed_domains": list of strings, "links_to_follow": string, "follow_patterns": list of strings, "exclude_patterns": list of strings, "respect_nofollow": boolean, "templates": list of template objects, "init_requests": list of request objects, } Attributes: start_urls : list of strings The list of URLs the spider will start crawling from. Start urls are expected to point to an HTML page, whose links will be followed according to the url filters attributes (``allowed_domains``, ``links_to_follow``, etc.). If you need a custom link extraction behavior (for example, if your starting page is a csv or xml feed) consider to include a `Start request`_ in ``init_requests`` array. allowed_domains : list of strings : optional The list of domains that can be crawled. If set to an empty list it will allow any domain. If this variable is not set then the list of allowed domains is extracted from the start urls. links_to_follow : string Either one of these values: * ``none``: no links will be followed (only the start urls will be visited) * ``patterns``: links will be followed according to the regular expressions in ``follow_patterns`` and ``exclude_patterns`` attributes follow_patterns : list of strings : optional A list of regular expressions that define urls to follow. If empty, it will follow all links. This field is ignored if ``links_to_follow`` is other than ``patterns``. exclude_patterns : list of strings : optional A list of regular expressions that define urls to avoid following. It has precedence over ``follow_patterns``. respect_nofollow : boolean Whether to respect `rel=nofollow`_. Defaults to false. templates : list of objects A list of template objects. init_requests : list of request objects : optional A list of requests objects that will be executed (sequentially, in order) when the spider is opened and before visiting the start urls. page_actions : list of page action objects : optional A list of page actions (like clicking a button or typing text into a field) that will be executed (sequentially) on the page. Template -------- Attributes: page_id : string An identifier for the template page_type : string Either one of these values: * ``links``: indicates this template contains "links to follow" annotations * ``item``: indicates this template contains field annotations. It can also contain "links to follow" annotations. scrapes : string The name of the item this template annotates. It must be defined in `items.json`. extractors : mapping A mapping from field names to extractor ids (which must be defined in `extractors.json`) url : string The URL of the page from which the template was generated from. annotated_body : string The annotated body. original_body : string The original body (without annotations). selectors : mapping A mapping from field names to selector objects. If provided when this template extracts an item from a response, the selectors will be run on the page and results added to the item. Selector -------- Attributes: type : string The type of the selector, can be either ``css`` or ``xpath``. selector : string The selector expression Extractor --------- Attributes: type_extractor : string : optional If defined, it will override the default extractor for the field. For allowed values, see the ``type`` attribute in `Field object`. regular_expression : string : optional A regular expression that will be applied to the extracted data, to refine its result. It will be applied after the base extractor (either defined in the field type or through the ``type_extractor`` attribute). The regex must extract at least one group (parenthesis enclosed part), in order to be considered a match. The groups matched will be concatenated for generating the final result. Examples ======== This is a complete example of an items.json file:: { "person": { "fields": { "first_name": { "required": "true", "type": "string", "vary": "true" }, "last_name": { "required": "true", "type": "string", "vary": "true" } } }, "job": { "fields": { "company": { "required": "true", "type": "string", "vary": "true" }, "position": { "required": "true", "type": "string", "vary": "true" } } } } Request ======= A request object represents a request that will be made by slybot:: { "type": string, # ... type-specific arguments ... } Attributes: type : string The type of the request. This is the only attribute that is present in all request types. Other attributes are available depending on the request type. Start request ------------- Used to represent a plain start url:: { "type": "start", "url": string, "link_extractor": link extractor object, } Attributes: type : string The type of request, which for start requests must be ``start``. url: string The start page URL. link_extractor : link extractor : optional Allow to associate a link extractor object to the request, in order to be applied to its response. If given, the request callback will be constructed using the specified link extractor in order to extract links. If not given, the assigned callback will be the spider ``parse`` method, so request will work as if it were a single url inside `Spider`_ ``start_urls``. Login request ------------- Used to represent a request to perform login:: { "type": "login", "loginurl": string, "username": string, "password": string, } Attributes: type : string The type of request, which for login requests must be ``login``. loginurl : string The login page URL. This is the page containing the login form, not the URL where the form data is POSTed. username : string The login username. password : string The login password. Generic form request -------------------- Used to represent a request to a generic form:: { "type": "form", "form_url": "http://www.mysite.com/search.php", "xpath" : "//form[@name=search_form]", "fields" : [ { "xpath": "//*[@name=state]", "type": "iterate", "value": ".*", }, { "xpath": "//*[@name=country]", "type": "constants", "value": ["US"] } ] } Attributes: type : string The type of request, which for generic form requests must be ``form``. form_url : string The form page URL. This is the page containing the form, not the URL where the form data is POSTed. xpath : string A xpath expression to access the form to be posted. fields : list A list of fields to be posted with the form. Page Action ----------- Used to represent an action to be performed on a page:: { "type": "click", "selector": "#show_more", "accept": "/product/[0-9]+", "reject": "/product/(0|999)" } Attributes: type : string Either one of these values: * ``wait``: Wait for a specified amount of time before continuing * ``click``: Click something on the page * ``set``: Set a text field or select box value * ``scroll``: Scroll an element timeout : number Only when type is ``wait``: Ammount of time to wait selector : string Only when type is ``click``, ``set`` or ``scroll``: CSS selector of the elements to apply the action to. If the selector matches several elements, action is applied to all. value : string Only when type is ``set``: Value to set the field or select box to. percent : number Only when type is ``scroll``: Scroll vertically this percentage of the page. accept : regex (optional) Only run the action in pages which URL matches the regex reject: regex (optional) Don't run the action in pages which URL matches the regex Generic Form Field ------------------ Used to represent a field in a generic form. Attributes: xpath : string A xpath expression to access the field to be posted. type : string The type attribute defines how the field will be posted, it supports the following values: * "constants": Use a list of values defined in the value field. * "iterate": Use the option values defined in a select field. The value for this type is a regex expression used to match the options for the select. If empty it will use all the select options. * "inurl": Use a list of values obtained from the URL defined in the "value" attribute. The URL must point to a text file with a value per line. name : string : optional If this field is set then it will be used as the option name sent to the server overriding the field name. This can be used to submit values for fields not present in the form (this is useful in some cases like when the data submitted is modified by javascript, i.e in aspx forms). value : string : optional Define the value(s) to be submitted with this field. The sintax of this attribute depends of the field type (see above). This attribute supports the use of spider arguments, using the following sintax: {arg1}, this will use the value of the arg1. Link Extractor -------------- Defines a link extractor object. Except in the case of ``module`` type, all types configure a base link extractor class. But all link extractors must have the same interface (see slybot.linkextractor.BaseLinkExtractor) Attributes: type : string Defines how to interpret the string in the 'value' attribute. Current supported values for this attribute are: * ``csv_column`` - value is an integer index indicating a column number. Link source is regarded as csv formatted ``scrapy.http.TextResponse``. * ``xpath`` - value is an xpath. Link source is regarded as a ``scrapy.http.XmlResponse``. * ``regex`` - value is a regular expression. Link source is regarded as a ``scrapy.http.TextResponse``. * ``module`` - value is a python module path. Link source is a ``scrapy.http.Response`` or subclass, depending on implementation requirements. * ``html`` - a shortcut for ``module`` type with value ``slybot.linkextractor.HtmlLinkExtractor``. The content of the value attribute is ignored. Source is a ``scrapely.htmlpage.HtmlPage`` object or a ``scrapy.http.HtmlResponse``. * ``rss`` - a shortcut for ``xpath`` type with value ``//item/link/text()``. The content of the value attribute is ignored. * ``sitemap`` - shortcut for ``xpath`` type with value ``//urlset/url/loc/text()`` and removed namespaces. The content of the value attribute is ignored. * ``atom`` - shortcut for ``xpath`` type with value ``//link/@href`` and removed namespaces. The content of the value attribute is ignored. value : any The content is specific to the defined type. Additional attributes can be given. They are passed as extra keyword argument for the link extractor class constructor. Check ``slybot.linkextractor`` module. TODO ==== * should we combine everything into a single JSON file (like HAR format). It could still support excluding certain spiders. * what about global project metadata, like name or application (and version) used to generate the project? * cleanup built-in field types? * Template object: change ``page_id`` attribute to ``id``, or ``template_id``?. Same for ``page_type``. * Template page_type: why do we need both ``item`` and ``links``?. What happens if a field is required and not extracted, but there are links to follow? * Template: ``scrapes`` should only be set if page_type=item? * Extractor: ``type_extractor`` redundant? * Extractor: refactor to support other extractor types (xpath, python, css) and integrate with field types. * Field type: finish spec and integrate with extractors (after refactoring) .. _rel=nofollow: http://en.wikipedia.org/wiki/Nofollow ================================================ FILE: slybot/docs/spiderlets.rst ================================================ ========== Spiderlets ========== .. warning:: This functionality is experimental and its API may undergo changes from time to time. Use at your own risk and please contribute feedback to make it stable. The slybot spider alone is not able to solve all the crawling and extraction difficulties that may arise for every possible case: data presented in a way partially or not suitable for the similarity algorithm, arbitrary post data and ajax requests, complex url normalization not handled by an addon, etc. Spiderlets are a method to extend any AS spider in a way that everything it is possible to do with a normal scrapy spider, can be done with a spiderlet. Spiderlets are handled by a spider middleware. In order to be enabled, the setting ``SPIDERLETS_MODULE`` must be present, with the value being the module name that contains the spiderlets submodules. For example, if your spiderlets are in the module ``mylib.spiderlets``, then you set the value of ``SPIDERLETS_MODULE`` to ``mylib.spiderlets``. What is a spiderlet ___________________ A spiderlet is an instance of a python class which implements at least one of the predefined methods described below. In order to attach a spiderlet to a given spider, you use the class attribute ``name``. The value of this attribute must match the name of the spider: :: class MySpiderlet: name = "myspider" def process_request(self, request, response): ... return request def process_item(self, item, response): ... return item def process_start_request(self, request): ... return request def parse_login_page(self, response): ... return request Three of the methods, ``process_request``, ``process_item`` and ``process_start_request``, are attached to the output of the autoscraping spider. The autoscraping spider generates two kind of objects: a request or an item. And depending on the kind of object generated and the source, the spiderlet addon passes it to one or another method of your spiderlet. So, each item issued by the spider is passed to ``process_item``, and each request is passed to ``process_start_request`` or ``process_request``, depending on the source: a start url, or a request generated by the spider as a consequence of a link extraction from a received response. Starting requests usually need to be processed in a different way, and they don't have an associated response from which they were generated. ``process_request`` and ``process_start_request`` are commonly used for normalize request url, filter it, or override the request callback (eventually defined as a new method of the spiderlet). The default callback for every request generated by the spider is the ``parse`` method of the autoscraping spider. Whenever you need to generate a FormRequest for sending post data or simulating an AJAX call, you will need to create your own callbacks in the spiderlet and point the request callbacks to them. ``process_item`` is mostly used for item post processing. An important feature is that the values of the item fields returned by the autoscraping spider are always lists, even if it is single valued. So you have to consider this fact when you are accessing the item fields inside the ``process_item`` method. There is no restriction, however, on the types of data contained in the items returned by the spiderlet. The fourth method, ``parse_login_page``, is of a different kind. Instead of process an output from the spider, it process an incoming response, and it is applied only to those responses which its callback is the ``parse_login_page`` method of the autoscraping spider. If you define ``parse_login_page`` method in your spiderlet, the request callback will be overridden by this new one. This feature allows to write your own login handler when the slybot default one (based on the generic solution implemented in the `loginforms library `_) does not fit well for a given case. Another very practical feature of a spiderlet is that you can access the autoscraping spider methods and attributes with the spiderlet attribute ``self.spider``. ``self.spider.log`` or ``self.spider.parse`` are among the most commonly methods needed to be accessed from the spiderlet. ================================================ FILE: slybot/requirements-clustering.txt ================================================ -r requirements.txt page_clustering==0.0.1 ================================================ FILE: slybot/requirements-test.txt ================================================ tox==3.12.1 nose==1.3.7 nose-timer==0.7.5 doctest-ignore-unicode==0.1.2 setuptools>=41.0.1 ================================================ FILE: slybot/requirements.txt ================================================ # Slybot requirements numpy==1.16.4 Scrapy==1.6.0 scrapely==0.13.5 loginform==1.2.0 lxml==4.3.4 dateparser==0.7.1 python-dateutil==2.8.0 jsonschema==2.6.0 six==1.12.0 scrapy-splash==0.7.2 page_finder==0.1.8 chardet==3.0.4 ================================================ FILE: slybot/scrapy.cfg ================================================ [settings] default = slybot.settings ================================================ FILE: slybot/setup.py ================================================ from os.path import join, abspath, dirname, exists from slybot import __version__ from setuptools import setup, find_packages from setuptools.command.bdist_egg import bdist_egg from setuptools.command.sdist import sdist def build_js(): root = abspath(dirname(__file__)) base_path = abspath(join(root, '..', 'splash_utils')) if not exists(base_path): base_path = abspath(join(root, '..', 'slyd', 'splash_utils')) files = ('waitAsync.js', 'perform_actions.js') fdata = [] for fname in files: try: with open(join(base_path, fname)) as f: fdata.append(f.read()) except IOError: print( 'WARNING: Could not find JavaScript files to build splash ' 'scripts. Using pre-built assets if available instead') return js_file = abspath(join(root, 'slybot', 'splash-script-combined.js')) with open(js_file, 'w') as f: f.write(';(function(){\n%s\n})();' % '\n'.join(fdata)) class bdist_egg_command(bdist_egg): def run(self): build_js() bdist_egg.run(self) class sdist_command(sdist): def run(self): build_js() sdist.run(self) install_requires = ['Scrapy', 'scrapely', 'loginform', 'lxml', 'jsonschema', 'dateparser', 'scrapy-splash', 'page_finder', 'six', 'chardet'] extras = { 'tests': ['nose', 'nose-timer', 'doctest-ignore-unicode', 'tox'], 'clustering': ['page_clustering'] } setup(name='slybot', version=__version__, license='BSD', description='Slybot crawler', author='Scrapy project', author_email='info@scrapy.org', url='http://github.com/scrapinghub/portia', packages=find_packages(exclude=('tests', 'tests.*')), platforms=['Any'], scripts=['bin/slybot', 'bin/portiacrawl'], install_requires=install_requires, extras_require=extras, package_data={'': ['slybot/splash-script-combined.js']}, include_package_data=True, cmdclass={ 'bdist_egg': bdist_egg_command, 'sdist': sdist_command }, classifiers=[ 'Development Status :: 4 - Beta', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', ]) ================================================ FILE: slybot/slybot/__init__.py ================================================ __version__ = '0.13.3' ================================================ FILE: slybot/slybot/baseurl.py ================================================ """ html page utils """ import re from six.moves.urllib.parse import urljoin from scrapely.htmlpage import parse_html, HtmlTagType ABSURLRE = re.compile("^https?\:\/\/") DOCTYPERE = re.compile("", re.S | re.I) def _is_abs_url(url): return bool(ABSURLRE.match(url)) def insert_base_url(html, base): """ Inserts the given base url if does not exist in html source, or replace the existing if needed """ baseurl = baseelement = headelement = htmlelement = None for element in parse_html(html): if getattr(element, "tag", None) == "base": baseurl = element.attributes.get("href", None) baseelement = element elif getattr(element, "tag", None) == "head" and \ element.tag_type == HtmlTagType.OPEN_TAG: headelement = element elif getattr(element, "tag", None) == "html" and \ element.tag_type == HtmlTagType.OPEN_TAG: htmlelement = element if baseurl: if not _is_abs_url(baseurl): absurl = urljoin(base, baseurl) # replace original base tag basetag = '' % absurl html = html[:baseelement.start] + basetag + html[baseelement.end:] else: # Generate new base element and include basetag = '' % base if headelement: insertpos = headelement.end else: if htmlelement: basetag = "\n%s\n" % basetag insertpos = htmlelement.end else: doctype_match = DOCTYPERE.search(html) if doctype_match: insertpos = doctype_match.end() else: insertpos = 0 html = html[:insertpos] + basetag + html[insertpos:] return html def get_base_url(htmlpage): """Return the base url of the given HtmlPage""" for element in htmlpage.parsed_body: if getattr(element, "tag", None) == "base": return element.attributes.get("href") or htmlpage.url return htmlpage.url ================================================ FILE: slybot/slybot/closespider.py ================================================ """ This extension closes spiders after they have been crawling inefficiently for a while Each SLYCLOSE_SPIDER_CHECK_PERIOD seconds, it checks that at least SLYCLOSE_SPIDER_PERIOD_ITEMS have been extracted along the last time interval of same length. """ from twisted.internet import task from scrapy.xlib.pydispatch import dispatcher from scrapy import signals from scrapy.exceptions import NotConfigured DEFAULT_CHECK_PERIOD = 3600 DEFAULT_PERIOD_MIN_ITEMS = 200 class SlybotCloseSpider(object): def __init__(self, crawler): if not crawler.settings.getbool("SLYCLOSE_SPIDER_ENABLED"): raise NotConfigured self.crawler = crawler self.check_period = crawler.settings.getint("SLYCLOSE_SPIDER_CHECK_PERIOD", DEFAULT_CHECK_PERIOD) self.period_items = crawler.settings.getint("SLYCLOSE_SPIDER_PERIOD_ITEMS", DEFAULT_PERIOD_MIN_ITEMS) self.items_in_period = 0 dispatcher.connect(self.spider_opened, signal=signals.spider_opened) dispatcher.connect(self.spider_closed, signal=signals.spider_closed) dispatcher.connect(self.item_scraped, signal=signals.item_scraped) def spider_opened(self, spider): self.task = task.LoopingCall(self._check_crawled_items, spider) self.task.start(self.check_period, now=False) def spider_closed(self, spider): if self.task.running: self.task.stop() def item_scraped(self, item, spider): self.items_in_period += 1 def _check_crawled_items(self, spider): if self.items_in_period >= self.period_items: self.items_in_period = 0 else: spider.log("Closing spider because of low item throughput. Items in last period: %d" % self.items_in_period) self.crawler.engine.close_spider(spider, 'slybot_fewitems_scraped') @classmethod def from_crawler(cls, crawler): return cls(crawler) ================================================ FILE: slybot/slybot/clustering.py ================================================ import json import logging import os from scrapely.htmlpage import HtmlPage from scrapy import signals from scrapy.exceptions import NotConfigured from scrapy.utils.request import request_fingerprint from scrapy.utils.project import data_path from slybot.plugins.scrapely_annotations.annotations import _CLUSTER_NA class PersistentClusteringMiddleware(object): def __init__(self, directory, reset=False, stats=None): try: import anydbm as _dbm except ImportError: import dbm as _dbm self.dbmodule = _dbm self.directory = directory self.reset = reset self.stats = stats self.clustering_enabled = False @classmethod def from_crawler(cls, crawler): s = crawler.settings if not s.getbool('PERSISTENT_PAGE_CLUSTERING'): raise NotConfigured directory = data_path(s.get('CLUSTERING_DIR', 'clustering')) reset = s.getbool('CLUSTERING_RESET') o = cls(directory, reset, crawler.stats) crawler.signals.connect(o.spider_opened, signal=signals.spider_opened) crawler.signals.connect(o.spider_closed, signal=signals.spider_closed) return o def spider_opened(self, spider): try: clustering = spider.plugins['Annotations'].clustering assert bool(clustering) == True self.clustering_enabled = True except (KeyError, AttributeError, AssertionError): logging.warning('Persistent page clustering has not been enabled ' 'because page clustering is not enabled for this ' 'spider') return if not os.path.exists(self.directory): os.makedirs(self.directory) dbpath = os.path.join(self.directory, spider.name) flag = 'n' if self.reset else 'c' self.db = self.dbmodule.open(dbpath, flag=flag) for data in getattr(self.db, 'itervalues', self.db.values)(): page, encoding = json.loads(data) clustering.add_page(HtmlPage(body=page.decode(encoding))) def spider_closed(self, spider): self.db.close() def process_spider_output(self, response, result, spider): """Store page tag details if page clustering was not available.""" saved = False for out in result: if (not saved and self.clustering_enabled and hasattr(out, 'get') and out.get('_template_cluster') == _CLUSTER_NA): key = request_fingerprint(response.request) logging.debug('Saving %s for clustering on next crawl', response.request) self.db[key] = json.dumps([response.body_as_unicode(), response.encoding]) saved = True yield out ================================================ FILE: slybot/slybot/dupefilter.py ================================================ """ Duplicates filter middleware for autoscraping """ from scrapy.exceptions import NotConfigured from scrapy.exceptions import DropItem from slybot.item import create_item_version class DupeFilterPipeline(object): def __init__(self, settings): if not settings.getbool('SLYDUPEFILTER_ENABLED'): raise NotConfigured self._itemversion_cache = {} @classmethod def from_crawler(cls, crawler): return cls(crawler.settings) def process_item(self, item, spider): """Checks whether a scrapy item is a dupe, based on version (not vary) fields of the item class""" if (not hasattr(item, 'version_fields') or not item.version_fields or item.get('_type') != getattr(item, '_display_name', 0)): return item version = create_item_version(item) if version in self._itemversion_cache: old_url = self._itemversion_cache[version] raise DropItem("Duplicate product scraped at <%s>, first one was " "scraped at <%s>" % (item["url"], old_url)) self._itemversion_cache[version] = item["url"] return item ================================================ FILE: slybot/slybot/exporter.py ================================================ from scrapy.exporters import CsvItemExporter from scrapy.conf import settings class SlybotCSVItemExporter(CsvItemExporter): def __init__(self, *args, **kwargs): kwargs['fields_to_export'] = settings.getlist('CSV_EXPORT_FIELDS') or None super(SlybotCSVItemExporter, self).__init__(*args, **kwargs) ================================================ FILE: slybot/slybot/extractors.py ================================================ import re import six from scrapely.extractors import htmlregion from scrapely.htmlpage import HtmlPageRegion from slybot.fieldtypes import FieldTypeManager from slybot.item import SlybotFieldDescriptor, SlybotItemDescriptor def create_regex_extractor(pattern): r"""Create extractor from a regular expression. Only groups from match are extracted and concatenated, so it is required to define at least one group. Ex: >>> extractor = create_regex_extractor("(\d+).*(\.\d+)") >>> extractor(u"The price is 45.50 $") u'45.50' """ ereg = re.compile(pattern, re.S) def _extractor(txt, htmlpage=None): if txt is None: return m = ereg.search(txt) if m: return htmlregion(u"".join([g for g in m.groups() or m.group() if g])) name = u"Regex: %s" % pattern if six.PY2: name = name.encode('utf-8') _extractor.__name__ = name return _extractor def create_type_extractor(_type): types = FieldTypeManager() extractor = types.type_processor_class(_type)() def _extractor(txt, htmlpage=None): if txt is None: return page = getattr(htmlpage, 'htmlpage', htmlpage) if not hasattr(txt, 'text_content'): txt = HtmlPageRegion(page, txt) data = extractor.extract(txt) if data: return extractor.adapt(data, page) name = (u"Type Extractor: %s" % _type) if six.PY2: name = name.encode('utf-8') _extractor.__name__ = name return _extractor class PipelineExtractor: def __init__(self, *extractors): self.extractors = extractors def __call__(self, value): for extractor in self.extractors: value = extractor(value) if value else value return value @property def __name__(self): return repr(self.extractors) def apply_extractors(descriptor, template_extractors, extractors): type_processor_class = FieldTypeManager().type_processor_class if isinstance(template_extractors, dict): template_extractors = template_extractors.items() attribute_map = descriptor.attribute_map for field_name, field_extractors in template_extractors: equeue = [] for eid in field_extractors: e_doc = extractors.get(eid, {}) if "regular_expression" in e_doc: equeue.append( create_regex_extractor(e_doc["regular_expression"])) elif "type_extractor" in e_doc: # overrides default one try: display_name = attribute_map[field_name].description except KeyError: display_name = field_name field_type = type_processor_class(e_doc["type_extractor"])() attribute_map[field_name] = SlybotFieldDescriptor( field_name, display_name, field_type) if field_name not in attribute_map: # if not defined type extractor, use text type by default, as it is # by far the most commonly used attribute_map[field_name] = SlybotFieldDescriptor( field_name, field_name, type_processor_class("text")()) if equeue: equeue.insert(0, attribute_map[field_name].extractor) attribute_map[field_name].extractor = PipelineExtractor(*equeue) def add_extractors_to_descriptors(descriptors, extractors): new_extractors = {} for _id, data in extractors.items(): if "regular_expression" in data: extractor = create_regex_extractor(data['regular_expression']) else: extractor = create_type_extractor(data['type_extractor']) new_extractors[_id] = extractor for descriptor in descriptors.values(): if isinstance(descriptor, SlybotItemDescriptor): descriptor.extractors = new_extractors ================================================ FILE: slybot/slybot/fieldtypes/__init__.py ================================================ """ Field Types Spiders extracts items of a given type. These item types are defined by a schema, which specifies the type of each field in the item. This module contains FieldProcessor implementations, which are the classes responsible for custom processing of these types. We keep the types of scrapers supported flexible and allow different methods for each. In the future, we expect many different types, for example one might be a mechanical turk scraper and the fields would have to do user validation and provide error messages. """ from .text import ( RawFieldTypeProcessor, TextFieldTypeProcessor, SafeHtmlFieldTypeProcessor ) from .images import ImagesFieldTypeProcessor from .url import UrlFieldTypeProcessor from .number import NumberTypeProcessor from .point import GeoPointFieldTypeProcessor from .price import PriceTypeProcessor from .date import DateTimeFieldTypeProcessor class FieldTypeManager(object): _TYPEMAP = dict((c.name, c) for c in ( RawFieldTypeProcessor, TextFieldTypeProcessor, ImagesFieldTypeProcessor, NumberTypeProcessor, UrlFieldTypeProcessor, SafeHtmlFieldTypeProcessor, GeoPointFieldTypeProcessor, PriceTypeProcessor, DateTimeFieldTypeProcessor )) _names = sorted(_TYPEMAP.keys()) def available_type_names(self): """Find the names of all field types available. """ return self._names def type_processor_class(self, name): """Retrieve the class for the given extractor This can be useful to introspect on the constructor arguments. If no suitable type is found, it will default to the RawFieldTypeProcessor (no processing of extracted data is done). """ return self._TYPEMAP.get(name, RawFieldTypeProcessor) def type_processor_serializer(self, name): processor = self._TYPEMAP.get(name, RawFieldTypeProcessor) return getattr(processor, 'serializer', None) def all_processor_classes(self): """Retrieve all processor classes registered""" return list(self._TYPEMAP.values()) ================================================ FILE: slybot/slybot/fieldtypes/date.py ================================================ from datetime import datetime from dateparser.date import DateDataParser from scrapy.utils.spider import arg_to_iter from .text import TextFieldTypeProcessor class DateTimeFieldTypeProcessor(TextFieldTypeProcessor): """ Extracts a date from text >>> from scrapely.extractors import htmlregion >>> d = DateTimeFieldTypeProcessor() >>> d.extract(htmlregion(u" Jan 12, 2014 11:15AM
    ")) u'Jan 12, 2014 11:15AM' >>> d.adapt(u"Jan 12, 2014 11:15AM", None).strftime('%Y-%m-%dT%H:%M:%S') '2014-01-12T11:15:00' >>> d.adapt(u'no date here', None) """ DATETIME_FMT = "%Y-%m-%d %H:%M:%S" name = 'date' description = 'Extracts date and time information from a string' def extract(self, htmlregion): return super(DateTimeFieldTypeProcessor, self).extract(htmlregion) def adapt(self, text, htmlpage=None): try: return DateDataParser().get_date_data(text)['date_obj'] except ValueError: return @classmethod def serializer(cls, output): return [ o.strftime(cls.DATETIME_FMT) if isinstance(o, datetime) else str(o) for o in arg_to_iter(output) ] ================================================ FILE: slybot/slybot/fieldtypes/images.py ================================================ """Images.""" from scrapely.extractors import extract_image_url from slybot.fieldtypes.url import UrlFieldTypeProcessor class ImagesFieldTypeProcessor(UrlFieldTypeProcessor): name = 'image' description = 'extracts image URLs' def extract(self, text): if text is not None: return extract_image_url(text) or '' return '' ================================================ FILE: slybot/slybot/fieldtypes/number.py ================================================ """ Numeric data extraction """ from scrapely.extractors import contains_any_numbers, extract_number class NumberTypeProcessor(object): """NumberTypeProcessor Extracts a number from text >>> from scrapely.extractors import htmlregion >>> n = NumberTypeProcessor() >>> n.extract(htmlregion(u"there are no numbers here")) >>> n.extract(htmlregion(u"foo 34")) u'foo 34' >>> n.adapt(u"foo 34", None) u'34' If more than one number is present, nothing is extracted >>> n.adapt(u"34 48", None) is None True """ name = 'number' description = 'extracts a single number in the text passed' def extract(self, htmlregion): """Only matches and extracts strings with at least one number""" return contains_any_numbers(htmlregion.text_content) def adapt(self, text, htmlpage=None): return extract_number(text) ================================================ FILE: slybot/slybot/fieldtypes/point.py ================================================ class GeoPointFieldTypeProcessor(object): """Renders point with tags""" name = 'geopoint' description = 'geo point' multivalue = True def extract(self, value): return value def adapt(self, value, htmlpage=None): return value ================================================ FILE: slybot/slybot/fieldtypes/price.py ================================================ """ Price field types """ from scrapely import extractors class PriceTypeProcessor(object): """Extracts price from text""" name = "price" description = "extracts a price decimal number in the text passed" def extract(self, htmlregion): return extractors.contains_any_numbers(htmlregion.text_content) def adapt(self, text, htmlpage=None): return extractors.extract_price(text) ================================================ FILE: slybot/slybot/fieldtypes/text.py ================================================ """ Text types """ import re from scrapely.extractors import text as extract_text, safehtml from w3lib.html import remove_tags _REMOVE_TAGID = re.compile(' data-tagid="\d+"').sub class _BaseTextProcessor(object): """basic text processor, defines identity functions, some of which are overridden in subclasses """ def extract(self, text): """Matches and extracts any string, as it is""" return _REMOVE_TAGID('', text) def adapt(self, text, htmlpage=None): return text class RawFieldTypeProcessor(_BaseTextProcessor): """Extracts the raw data, without processing. Data is escaped for presentation >>> from scrapely.extractors import htmlregion >>> r = RawFieldTypeProcessor() >>> html = htmlregion(u'

    test

    ') >>> r.extract(html) u'

    test

    ' >>> r.adapt(html, None) u'

    test

    ' """ name = 'raw html' description = 'raw html as it appears in the page' class TextFieldTypeProcessor(_BaseTextProcessor): """Extracts strings, removing all HTML markup >>> from scrapely.extractors import htmlregion >>> p = TextFieldTypeProcessor() >>> html = htmlregion(u'

    test

    !') >>> extracted = p.extract(html) >>> extracted u'test !' >>> p.adapt(extracted, None) u'test !' >>> html = htmlregion(u'

     \\n

    ') >>> p.extract(html) u'' """ name = 'text' description = 'extracts text from web pages, cleaning all markup' def extract(self, htmlregion): text = getattr(htmlregion, 'text_content', htmlregion) return remove_tags(extract_text(text)).strip() class SafeHtmlFieldTypeProcessor(_BaseTextProcessor): """Extracts strings, with only a safe subset of HTML remaining Extraction checks for presence of text content, and adapt transforms the HTML >>> from scrapely.extractors import htmlregion >>> p = SafeHtmlFieldTypeProcessor() >>> html = htmlregion(u'

    test

    foo') >>> p.extract(html) u'

    test

    foo' >>> p.adapt(html) u'

    test

    foo' >>> html = htmlregion(u'

    value') >>> p.extract(html) u'

    value' >>> p.adapt(html) u'

    value

    ' html without text must not be extracted >>> html = htmlregion(u'
    ') """ name = 'safe html' description = 'removes all but a small subset of html tags' def extract(self, htmlregion): if extract_text(htmlregion.text_content): return htmlregion def adapt(self, text, htmlpage=None): """Remove html markup""" return safehtml(text) ================================================ FILE: slybot/slybot/fieldtypes/url.py ================================================ import re from six.moves.urllib.parse import urljoin from scrapely.extractors import url as strip_url from scrapy.utils.url import safe_download_url from scrapy.utils.markup import unquote_markup from slybot.baseurl import get_base_url disallowed = re.compile('[\x00-\x1F\x7F]') class UrlFieldTypeProcessor(object): """Renders URLs as links""" name = 'url' description = 'URL' limit = 80 def extract(self, text): if text is not None: return strip_url(text) return '' def adapt(self, text, htmlpage=None): if htmlpage is None: return text if text is None: return encoding = getattr(htmlpage, 'encoding', 'utf-8') text = text.encode(encoding) unquoted = unquote_markup(text, encoding=encoding) cleaned = strip_url(disallowed.sub('', unquoted)) base = get_base_url(htmlpage).encode(encoding) base_url = strip_url(unquote_markup(base, encoding=encoding)) joined = urljoin(base_url, cleaned) return safe_download_url(joined) ================================================ FILE: slybot/slybot/generic_form.py ================================================ import re import itertools from collections import OrderedDict from lxml import html from scrapy.http.request.form import _get_inputs class GenericForm: def __init__(self, **kwargs): self.kwargs = kwargs def _pick_node(self, doc, selector): nodes = doc.xpath(selector['xpath']) if nodes: return nodes[0] def _filter_by_regex(self, lines, regex): search_regex = re.compile(regex).search return [l for l in lines if search_regex(l)] def _get_field_values(self, form, field_descriptor): if 'name' in field_descriptor: field_name = field_descriptor['name'] else: select_field = self._pick_node(form, field_descriptor) field_name = select_field.name field_type = field_descriptor['type'] if field_type == 'constants': return [[field_name, option] for option in self.get_value(field_descriptor)] elif field_type == 'iterate': select_field = self._pick_node(form, field_descriptor) values = self._filter_by_regex(select_field.value_options, self.get_value(field_descriptor)) return [[select_field.name, option] for option in values] elif field_type == 'inurl': return [[field_name, option] for option in field_descriptor['file_values']] def get_value(self, field_descriptor): values = field_descriptor.get('value', '') if isinstance(values, list): return [val.format(**self.kwargs) for val in values] else: return values.format(**self.kwargs) def set_values_url_field(self, field_descriptor, body): field_descriptor['file_values'] = body.split('\n') def get_url_field(self, form_descriptor): for i, field_descriptor in enumerate(form_descriptor['fields']): if (field_descriptor['type'] == 'inurl' and (not 'file_values' in field_descriptor or not field_descriptor['file_values'])): yield i, field_descriptor def fill_generic_form(self, url, body, form_descriptor): doc = html.document_fromstring(body, base_url=url) form = self._pick_node(doc, form_descriptor) if form is None: raise Exception('Generic form not found') # Get all the possible inputs for each field values = [self._get_field_values(form, field) for field in form_descriptor['fields']] for params in itertools.product(*values): form_values = OrderedDict(_get_inputs(form, None, False, None, None)) for name, option in params: form_values[name] = option yield list(form_values.items()), form.action or form.base_url, form.method ================================================ FILE: slybot/slybot/item.py ================================================ import hashlib from collections import defaultdict, namedtuple from scrapy.item import DictItem, Field, Item from scrapely.descriptor import ItemDescriptor, FieldDescriptor from slybot.fieldtypes import FieldTypeManager FieldProcessor = namedtuple('FieldProcessor', ['name', 'description', 'extract', 'adapt']) class SlybotItem(DictItem): # like DictItem.__setitem__ but doesn't check the field is declared def __setitem__(self, name, value): self._values[name] = value def display_name(self): return self._display_name @classmethod def create_iblitem_class(cls, schema): class IblItem(cls, Item): ftm = FieldTypeManager() fields = defaultdict(dict) version_fields = [] _display_name = schema.get('name') for _name, _meta in schema.get('fields', {}).items(): name = _meta.get('name', _name) serializer = ftm.type_processor_serializer(_meta.get('type')) if serializer: _meta['serializer'] = serializer fields[name] = Field(_meta) if not _meta.get("vary", False): version_fields.append(name) version_fields = sorted(version_fields) return IblItem def create_slybot_item_descriptor(schema, schema_name=""): field_type_manager = FieldTypeManager() descriptors = [] for pname, pdict in schema.get('fields', {}).items(): required = pdict['required'] pdisplay_name = pdict.get('name', pname) pclass = field_type_manager.type_processor_class(pdict['type']) processor = pclass() descriptor = SlybotFieldDescriptor(pname, pdisplay_name, processor, required) descriptors.append(descriptor) return SlybotItemDescriptor(schema_name, schema.get('name', schema_name), descriptors) class SlybotFieldDescriptor(FieldDescriptor): """Extends the scrapely field descriptor to use slybot fieldtypes and to be created from a slybot item schema """ def __init__(self, name, description, field_type_processor, required=False): """Create a new SlybotFieldDescriptor with the given name and description. The field_type_processor is used for extraction and is publicly available """ FieldDescriptor.__init__(self, name, description, field_type_processor.extract, required) # add an adapt method self.adapt = field_type_processor.adapt self._processor = field_type_processor @property def processor(self): return FieldProcessor(self._processor.name, self._processor.description, self.extractor, self.adapt) def __str__(self): return "SlybotFieldDescriptor(%s, %s)" % (self.name, self._processor.name) class SlybotItemDescriptor(ItemDescriptor): def __str__(self): return "SlybotItemDescriptor(%s)" % self.name def copy(self): attribute_descriptors = [] for d in self.attribute_map.values(): attribute_descriptors.append( SlybotFieldDescriptor(d.name, d.description, d.processor, d.required)) return SlybotItemDescriptor(self.name, self.description, attribute_descriptors) def create_item_version(item): """Item version based on hashlib.sha1 algorithm""" if not item.version_fields: return _hash = hashlib.sha1() for attrname in item.version_fields: _hash.update(repr(item.get(attrname)).encode('utf-8')) return _hash.digest() ================================================ FILE: slybot/slybot/linkextractor/__init__.py ================================================ """ Link extraction for auto scraping """ from scrapy.utils.misc import load_object from .base import BaseLinkExtractor, ALLOWED_SCHEMES from .html import HtmlLinkExtractor from .pagination import PaginationExtractor from .xml import XmlLinkExtractor, RssLinkExtractor, SitemapLinkExtractor, AtomLinkExtractor from .regex import RegexLinkExtractor from .ecsv import CsvLinkExtractor _TYPE_MAP = ( # type, class, ignore value ('regex', RegexLinkExtractor, False), ('xpath', XmlLinkExtractor, False), ('column', CsvLinkExtractor, False), ('html', HtmlLinkExtractor, True), ('pagination', PaginationExtractor, True), ('rss', RssLinkExtractor, True), ('sitemap', SitemapLinkExtractor, True), ('atom', AtomLinkExtractor, True), ) def create_linkextractor_from_specs(specs): """Return a link extractor instance from specs. By default, return a HtmlLinkExtractor. """ specs = specs.copy() ltype, value = specs.pop('type'), specs.pop('value') if ltype == 'module': cls = load_object(value) return cls(**specs) for key, cls, ignore in _TYPE_MAP: if key == ltype: if ignore: return cls(**specs) return cls(value, **specs) raise ValueError("Invalid link extractor type specification") ================================================ FILE: slybot/slybot/linkextractor/base.py ================================================ """ Link extraction for auto scraping """ import re import os import posixpath from six.moves.urllib.parse import urlparse from scrapy.linkextractors import IGNORED_EXTENSIONS _ONCLICK_LINK_RE = re.compile("(?P('|\"))(?P.+?)(?P=sep)") _ignored_exts = frozenset(['.' + e for e in IGNORED_EXTENSIONS]) # allowed protocols ALLOWED_SCHEMES = frozenset(['http', 'https', None, '']) class BaseLinkExtractor(object): def __init__(self, max_url_len=2083, ignore_extensions=_ignored_exts, allowed_schemes=ALLOWED_SCHEMES): """Creates a new LinkExtractor The defaults are a good guess for the first time crawl. After that, we expect that they can be learned. """ self.max_url_len = max_url_len self.ignore_extensions = ignore_extensions self.allowed_schemes = allowed_schemes def _extract_links(self, source): raise NotImplementedError def links_to_follow(self, source): """Returns normalized extracted links""" for link in self._extract_links(source): link = self.normalize_link(link) if link is not None: yield link def normalize_link(self, link): """Normalize a link >>> from scrapy.link import Link >>> le = BaseLinkExtractor() >>> l = Link('http://scrapinghub.com/some/path/../dir') >>> le.normalize_link(l).url 'http://scrapinghub.com/some/dir' >>> l = Link('http://scrapinghub.com/some//./path/') >>> le.normalize_link(l).url 'http://scrapinghub.com/some/path/' Files with disallowed extentions or protocols are not returned >>> le.normalize_link(Link('myimage.jpg')) is None True >>> le.normalize_link(Link('file:///tmp/mydoc.htm')) is None True >>> le.normalize_link(Link('http://scrapinghub.com')).url 'http://scrapinghub.com/' Fragments are removed >>> le.normalize_link(Link('http://example.com/#something')).url 'http://example.com/' >>> le.normalize_link(Link('http://example.com/#something')).fragment 'something' >>> le.normalize_link(Link('http://scrapinghub.com#some fragment')).url 'http://scrapinghub.com/' Ajax crawling >>> le.normalize_link(Link('http://example.com/#!something')).url 'http://example.com/?_escaped_fragment_=something' >>> le.normalize_link(Link('http://example.com/page.html?arg=1#!something')).url 'http://example.com/page.html?arg=1&_escaped_fragment_=something' """ if len(link.url) > self.max_url_len: return parsed = urlparse(link.url) extention = os.path.splitext(parsed.path)[1].lower() if parsed.scheme not in self.allowed_schemes or \ extention in self.ignore_extensions: return # path normalization path = parsed.path or '/' path = path if path[0] != '.' else '/' + path path = posixpath.normpath(path) if parsed.path.endswith('/') and not path.endswith('/'): path += '/' if parsed.fragment.startswith('!'): query = '_escaped_fragment_=%s' % parsed.fragment[1:] query = parsed.query + '&' + query if parsed.query else query parsed = parsed._replace(query=query) link.fragment = parsed.fragment if path != parsed.path or parsed.fragment: link.url = parsed._replace(path=path, fragment='').geturl() return link ================================================ FILE: slybot/slybot/linkextractor/ecsv.py ================================================ from __future__ import absolute_import import csv from six import string_types, StringIO, PY2 from scrapy.link import Link from .base import BaseLinkExtractor # see http://docs.python.org/2/library/csv.html#csv-fmt-params _FORMAT_PARAMETERS = ( ('delimiter', ','), ('quotechar', '"'), ('doublequote', True), ('escapechar', None), ('lineterminator', '\r\n'), ('skipinitialspace', False), ('strict', False), ) class CsvLinkExtractor(BaseLinkExtractor): def __init__(self, column=0, **kwargs): self.fmtparams = dict((key, kwargs.pop(key, default)) for key, default in _FORMAT_PARAMETERS) if PY2: for key, val in self.fmtparams.items(): if isinstance(val, unicode): self.fmtparams[key] = val.encode() super(CsvLinkExtractor, self).__init__(**kwargs) self.allowed_schemes = [x for x in self.allowed_schemes if x and isinstance(x, string_types)] self.column = column def _extract_links(self, response): buff = StringIO(response.text) reader = csv.reader(buff, **self.fmtparams) for row in reader: if len(row) > self.column: yield Link(row[self.column]) ================================================ FILE: slybot/slybot/linkextractor/html.py ================================================ """ Link extraction for auto scraping """ import re import six from six.moves.urllib.parse import urljoin from six.moves.html_entities import name2codepoint from scrapy.link import Link from scrapy.http import HtmlResponse from scrapely.htmlpage import HtmlTag, HtmlTagType from w3lib.html import replace_entities from slybot.linkextractor.base import BaseLinkExtractor from slybot.utils import htmlpage_from_response _META_REFRESH_CONTENT_RE = re.compile(r"(?P(\d*\.)?\d+)\s*;\s*url=(?P.*)") _ONCLICK_LINK_RE = re.compile("(?P('|\"))(?P.+?)(?P=sep)") _ENTITIES_TO_KEEP = frozenset({c for c in name2codepoint} - {'amp', 'quot', 'lt', 'gt'}) def remove_entities(text, encoding): return replace_entities(text, keep=_ENTITIES_TO_KEEP, encoding=encoding) class HtmlLinkExtractor(BaseLinkExtractor): """Link extraction for auto scraping Links (urls and the anchor text) are extracted from HtmlPage objects. Some safe normalization is done (always correct, does not make assumptions about how the site handles URLs). It allows some customization, which we expect to learn for specific websites from the crawl logs. """ def _extract_links(self, response_or_htmlpage): """Extract links to follow from an html page This uses `iterlinks` to read the links in the page. """ if isinstance(response_or_htmlpage, HtmlResponse): response_or_htmlpage = htmlpage_from_response(response_or_htmlpage) return iterlinks(response_or_htmlpage) def iterlinks(htmlpage): """Iterate through the links in the HtmlPage passed For example: >>> import six >>> from scrapy.link import Link >>> from scrapely.htmlpage import HtmlPage >>> try: ... if type(unicode) == type: ... utext = lambda x: x ... except NameError: ... class utext(str): ... def __repr__(self): return 'u{}'.format(super().__repr__()) >>> def link_repr(self): ... text = self.text ... if isinstance(text, six.text_type): ... text = utext(self.text) ... return ( ... 'Link(url={!r}, text={!r}, fragment={!r}, nofollow={!r})' ... ).format(self.url, text, self.fragment, self.nofollow) >>> Link.__repr__ = link_repr >>> p = HtmlPage(body=u"Please visit Scrapinghub") >>> next(iterlinks(p)) Link(url='http://scrapinghub.com/', text=u'Scrapinghub', fragment='', nofollow=False) >>> p = HtmlPage(body=u"Go Home") >>> next(iterlinks(p)) Link(url='home.html', text=u'Home', fragment='', nofollow=False) When a url is specified, absolute urls are made: >>> p.url = 'http://scrapinghub.com/' >>> next(iterlinks(p)) Link(url='http://scrapinghub.com/home.html', text=u'Home', fragment='', nofollow=False) Base href attributes in the page are respected >>> p.body = u"see my project" >>> next(iterlinks(p)) Link(url='http://scrapinghub.com/myproject/index.html', text=u'project', fragment='', nofollow=False) >>> p.body = u"see my project" >>> next(iterlinks(p)) Link(url='http://scrape.io/index.html', text=u'project', fragment='', nofollow=False) Frameset and iframe urls are extracted >>> p = HtmlPage(body=u"\r\n\t\r\n \r\n \r\n
    \r\n\r\n
    \r\n\t\t\r\n
    \r\n\r\n
    Seeds & Supplies > Seeds > Vegetables > Squash & Pumpkins > Winter Squash
    \r\n\t\t\r\n\t\t\r\n\t\t
    Gold Nugget
    \r\n\t\t\r\n\t\t\r\n
    \r\n\t\t

    \r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \"Product
    Gold Nugget
    \r\n\t\t\t\tCucurbita maxima
    \r\n
    Tender Annual
    \r\n 
    \r\n\t\t\t\t

    1-2 lbs. (75-95 days) This early, extremely productive, compact bush variety is ideal for small gardens.  Miniature pumpkin-shaped fruits have pale red-orange skin and dry, sweet, dark orange flesh.  Great for stuffing, soups and pies.

    \r\n\t\t\t\t\r\n\t\t\t\t

    SHOW THIS ITEM TO OTHERS ►

    \r\n\t\t\t\t
    Planting Depth: 1"
    \r\nSoil Temp. for Germ.: 70-90°F
    \r\nDays to Germ.: 7-10
    \r\nPlant Spacing: 3'-4'Apart
    \nDays to Maturity: 75-95
    \r\nFull Sun
    \r\nModerate Water
    \r\n 
    \r\n\t\t\t\t

    \r\n\t\t\r\n\t\t\r\n\t\t\t\r\n \t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n \r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \r\n
    \r\n
    \r\n
    Choose a Size:
    \r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Squash, Winter, Gold Nugget- Pack of 20
     
    Item#: 01593     Price: $3.49
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t
    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Gold Nugget Winter Squash- Pack of 250
     
    Item#: 06696     Price: $19.99
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Select \"Ship To\" Recipient:\r\n\t\t \r\n

    New Recipient Name:
    Enter the recipient's first name only. We'll ask for the recipient's full name and address later.

    \r\n
    \r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n \r\n \r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\r\n\t\t\t\t
     \r\n \r\n

    \r\n
    CONTINUE SHOPPING ►\r\n\t\t\t\t\t\t \r\n \r\n\t\t\t\t\t\t
    \r\n\t\t\t\t
    \r\n
    \r\n
    \r\n\t\t\r\n \r\n\r\n\t\r\n
    \r\n
    \r\n

    Supporting Sustainable Organic Agriculture Since 1989

    \r\n

    In 1989, Seeds of Change began with a simple mission: to preserve biodiversity and promote sustainable, organic agriculture. By cultivating and sharing an extensive range of organically grown vegetable, flower, herb and cover crop seeds, we have honored that mission for almost 25 years.

    \r\n
    \r\n\r\n
    \r\n\r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\t\r\n\t\t\r\n\t\t \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t
    \r\n\t\t
    \r\n\t\t\t\t\t\r\n
    SEARCH
    \r\n\t\t\r\n\t\t \r\n\t\t \r\n\t\t\t\t\r\n\r\n\t\t
    \r\n\t\t\t\t \r\n\t\t\t\r\n\t\t\r\n \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n
    HOW TO ORDER
    Order Seeds Online
    Catalog Quick Order
    Contact Us

    FOLLOW US ON
    \r\n   
    Always certified organic
    \r\n\t\t\r\n\t\t\r\n\t\t
    \r\n\t \r\n\t\t\r\n\r\n\t\r\n\r\n\t\t\t\r\n\t\t\t
    \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n
    \r\n\t
    PRODUCTS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    GROWING TIPS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    CUSTOMER SERVICE
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n \r\n\t \r\n\t
    \r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n
    \r\n \r\n \r\n \r\n \r\n
    Shipping Info|Contact Us|Privacy Policy|Site Map|Organic Certification|Our Foods
    ®/TM Trademark © 2012 Seeds of Change..
    \r\n
    \r\n\r\n
    \r\n
    \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", "url": "http://www.seedsofchange.com/garden_center/product_details.aspx?item_no=PS14165", "original_body": "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\tSeeds of Change | Item Detail\r\n\r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n \r\n
    \r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\t\t\r\n\t\t\r\n\r\n\t\t\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n
      \r\n\r\n\r\n
    \r\nHOME|WHY ORGANIC?|DOWNLOAD A CATALOG|MY ACCOUNT|LOGIN\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n
    VIEW BASKET: 0 ITEMS($0.00)\r\n \r\n
    \r\n
    \r\n\r\n\r\n
      
    \r\n\t\t\r\n\t\t\t\r\n \r\n\r\n\r\n\r\n\r\n\r\n \r\n\t


    SEEDS & SUPPLIES 
    \r\n\t\r\n\t\t\r\n\t
    \r\n\t
    \r\n\t
    INFORMATION 
    \r\n\t\r\n\t

    \r\n\t
    SERVICES 
    \r\n\t\r\n\r\n\t\t\r\n\t\t
    \r\n\t\t
    \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t
     
     \r\n\t\t\r\n \r\n \r\n\t\r\n \r\n\r\n\r\n\r\n\r\n\t\r\n
    \r\n\t\r\n\t\r\n\t\r\n \r\n \r\n
    \r\n\r\n
    \r\n\t\t\r\n
    \r\n\r\n
    Seeds & Supplies > Seeds > Vegetables > Squash & Pumpkins > Winter Squash
    \r\n\t\t\r\n\t\t\r\n\t\t
    Gold Nugget
    \r\n\t\t\r\n\t\t\r\n
    \r\n\t\t

    \r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \"Item
    Gold Nugget
    \r\n\t\t\t\tCucurbita maxima
    \r\n
    Tender Annual
    \r\n 
    \r\n\t\t\t\t

    1-2 lbs. (75-95 days) This early, extremely productive, compact bush variety is ideal for small gardens.  Miniature pumpkin-shaped fruits have pale red-orange skin and dry, sweet, dark orange flesh.  Great for stuffing, soups and pies.

    \r\n\t\t\t\t\r\n\t\t\t\t

    SHOW THIS ITEM TO OTHERS ►

    \r\n\t\t\t\t
    Planting Depth: 1"
    \r\nSoil Temp. for Germ.: 70-90°F
    \r\nDays to Germ.: 7-10
    \r\nPlant Spacing: 3'-4'Apart
    \r\nDays to Maturity: 75-95
    \r\nFull Sun
    \r\nModerate Water
    \r\n 
    \r\n\t\t\t\t

    \r\n\t\t\r\n\t\t\r\n\t\t\t\r\n \t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n \r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \r\n
    \r\n
    \r\n
    Choose a Size:
    \r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Squash, Winter, Gold Nugget- Pack of 20
     
    Item#: 01593     Price: $3.49
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t
    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Gold Nugget Winter Squash- Pack of 250
     
    Item#: 06696     Price: $19.99
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Select \"Ship To\" Recipient:\r\n\t\t \r\n

    New Recipient Name:
    Enter the recipient's first name only. We'll ask for the recipient's full name and address later.

    \r\n
    \r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n \r\n \r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\r\n\t\t\t\t
     \r\n \r\n

    \r\n
    CONTINUE SHOPPING ►\r\n\t\t\t\t\t\t \r\n \r\n\t\t\t\t\t\t
    \r\n\t\t\t\t
    \r\n
    \r\n
    \r\n\t\t\r\n \r\n\r\n\t\r\n
    \r\n
    \r\n

    Supporting Sustainable Organic Agriculture Since 1989

    \r\n

    In 1989, Seeds of Change began with a simple mission: to preserve biodiversity and promote sustainable, organic agriculture. By cultivating and sharing an extensive range of organically grown vegetable, flower, herb and cover crop seeds, we have honored that mission for almost 25 years.

    \r\n
    \r\n\r\n
    \r\n\r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\t\r\n\t\t
     \r\n\t\t
    \r\n\t\t
    \r\n\t\t\t\t\t\r\n
    SEARCH
    \r\n\t\t\r\n\t\t \r\n\t\t \r\n\t\t\t\t\r\n\r\n\t\t
    \r\n\t\t\t\t \r\n\t\t\t\r\n\t\t\r\n \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n
    HOW TO ORDER
    Order Seeds Online
    Catalog Quick Order
    Contact Us

    FOLLOW US ON
    \r\n   
    Always certified organic
    \r\n\t\t\r\n\t\t\r\n\t\t
    \r\n\t \r\n\t\t\r\n\r\n\t\r\n\r\n\t\t\t\r\n\t\t\t
    \r\n\t\t
    \r\n\t\t
    \r\n\t\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n
    \r\n\t
    PRODUCTS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    GROWING TIPS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    CUSTOMER SERVICE
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n \r\n\t \r\n\t
    \r\n\t
    \r\n\r\n\r\n\r\n\r\n\r\n
    \r\n \r\n \r\n \r\n \r\n
    Shipping Info|Contact Us|Privacy Policy|Site Map|Organic Certification|Our Foods
    ®/TM Trademark © 2012 Seeds of Change..
    \r\n
    \r\n\r\n
    \r\n
    \r\n\r\n\r\n \r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", "scrapes": "default", "page_type": "item", "page_id": "4fac3b47688f920c7800000f", "version": "0.13.0", "selectors": { "breadcrumbs": { "type": "css", "selector": ".subhead a.breadcrumb" }, "image": { "type": "xpath", "selector": "//img[@id='ctl00_MainContentPlaceHolder_ProductDetails1_ProductImage']/@src" } } } ], "start_urls": [ "http://www.seedsofchange.com/garden_center/browse_category.aspx?id=123" ], "name": "seedsofchange", "exclude_patterns": [ "/tellafriend.aspx.+" ], "follow_patterns": [ "/garden_center/browse_category.aspx.+", "/garden_center/detailedCategoryDisplay.aspx.+", "/garden_center/product_details.aspx.+" ], "links_to_follow": "patterns", "respect_nofollow": true } ================================================ FILE: slybot/slybot/tests/data/SampleProject/spiders/seedsofchange2.json ================================================ { "templates": [ { "extractors": {}, "annotated_body": "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\tSeeds of Change | Item Detail\r\n\r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n \r\n
    \r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\t\t\r\n\t\t\r\n\r\n\t\t\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n
      \r\n\r\n\r\n
    \r\nHOME|WHY ORGANIC?|DOWNLOAD A CATALOG|MY ACCOUNT|LOGIN\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n
    VIEW BASKET: 0 ITEMS($0.00)\r\n \r\n
    \r\n
    \r\n\r\n\r\n
      
    \r\n\t\t\r\n\t\t\t\r\n \r\n\r\n\r\n\r\n\r\n\r\n \r\n\t


    SEEDS & SUPPLIES 
    \r\n\t\r\n\t\t\r\n\t
    \r\n\t
    \r\n\t
    INFORMATION 
    \r\n\t\r\n\t

    \r\n\t
    SERVICES 
    \r\n\t\r\n\r\n\t\t\r\n\t\t
    \r\n\t\t
    \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t
     
     \r\n\t\t\r\n \r\n \r\n\t\r\n \r\n\r\n\r\n\r\n\r\n\t\r\n
    \r\n\t\r\n\t\r\n\t\r\n \r\n \r\n
    \r\n\r\n
    \r\n\t\t\r\n
    \r\n\r\n
    Seeds & Supplies > Seeds > Vegetables > Onions
    \r\n\t\t\r\n\t\t\r\n\t\t
    Rossa Di Milano Onion
    \r\n\t\t\r\n\t\t\r\n
    \r\n\t\t

    \r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \"Product
    Rossa Di Milano Onion
    \r\n\t\t\t\tAlium cepa
    \nHeirloom/Rare\nHardy Biennial
    \r\nHardy Biennial
    \r\n 
    \r\n\t\t\t\t

    (110-120 days)  Midsized Italian variety.  Long to intermediate day red onion that tolerates cool climates.  Excellent keeper.  We have grown out thousands of bulbs and re-selected this variety to be the top quality variety that it once was.  4-5" bulbs are top-shaped, uniformly colored, and have tight skins.

    \r\n\t\t\t\t\r\n\t\t\t\t

    SHOW THIS ITEM TO OTHERS ►

    \r\n\t\t\t\t
    Planting Depth: 3/4-1"
    \r\nSoil Temp. for Germ.: 50-85°F
    \r\nDays to Germ.: 3-8
    \r\nAvg. Spacing: 10-15 seeds/ft. in rows 12-18" apart
    \r\nAvg. Seeding Rate: 4-6 lbs./acre
    \nDays to Maturity: 110-120
    \r\nFull Sun
    \r\nWater Often
    \r\n 
    \r\n\t\t\t\t

    \r\n\t\t\r\n\t\t\r\n\t\t\t\r\n \t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n \r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \r\n
    \r\n
    \r\n
    Choose a Size:
    \r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Onion, Rossa Di Milano- Pack of 350
     
    Item#: 01585     Price: $3.49
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t
    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Rossa Di Milano Onion- Pack of 3500
     
    Item#: 06654     Price: $19.99
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Select \"Ship To\" Recipient:\r\n\t\t \r\n

    New Recipient Name:
    Enter the recipient's first name only. We'll ask for the recipient's full name and address later.

    \r\n
    \r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n \r\n \r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\r\n\t\t\t\t
     \r\n \r\n

    \r\n
    CONTINUE SHOPPING ►\r\n\t\t\t\t\t\t \r\n \r\n\t\t\t\t\t\t
    \r\n\t\t\t\t
    \r\n
    \r\n
    \r\n\t\t\r\n \r\n\r\n\t\r\n
    \r\n
    \r\n

    Supporting Sustainable Organic Agriculture Since 1989

    \r\n

    In 1989, Seeds of Change began with a simple mission: to preserve biodiversity and promote sustainable, organic agriculture. By cultivating and sharing an extensive range of organically grown vegetable, flower, herb and cover crop seeds, we have honored that mission for almost 25 years.

    \r\n
    \r\n\r\n
    \r\n\r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\t\r\n\t\t
     \r\n\t\t
    \r\n\t\t
    \r\n\t\t\t\t\t\r\n
    SEARCH
    \r\n\t\t\r\n\t\t \r\n\t\t \r\n\t\t\t\t\r\n\r\n\t\t
    \r\n\t\t\t\t \r\n\t\t\t\r\n\t\t\r\n \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n
    HOW TO ORDER
    Order Seeds Online
    Catalog Quick Order
    Contact Us

    FOLLOW US ON
    \r\n   
    Always certified organic
    \r\n\t\t\r\n\t\t\r\n\t\t
    \r\n\t \r\n\t\t\r\n\r\n\t\r\n\r\n\t\t\t\r\n\t\t\t
    \r\n\t\t
    \r\n\t\t
    \r\n\t\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n
    \r\n\t
    PRODUCTS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    GROWING TIPS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    CUSTOMER SERVICE
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n \r\n\t \r\n\t
    \r\n\t
    \r\n\r\n\r\n\r\n\r\n\r\n
    \r\n \r\n \r\n \r\n \r\n
    Shipping Info|Contact Us|Privacy Policy|Site Map|Organic Certification|Our Foods
    ®/TM Trademark © 2012 Seeds of Change..
    \r\n
    \r\n\r\n
    \r\n
    \r\n\r\n\r\n \r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", "url": "http://www.seedsofchange.com/garden_center/product_details.aspx?item_no=PS15978", "original_body": "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\tSeeds of Change | Item Detail\r\n\r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n \r\n
    \r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\t\t\r\n\t\t\r\n\r\n\t\t\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n
      \r\n\r\n\r\n
    \r\nHOME|WHY ORGANIC?|DOWNLOAD A CATALOG|MY ACCOUNT|LOGIN\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n
    VIEW BASKET: 0 ITEMS($0.00)\r\n \r\n
    \r\n
    \r\n\r\n\r\n
      
    \r\n\t\t\r\n\t\t\t\r\n \r\n\r\n\r\n\r\n\r\n\r\n \r\n\t


    SEEDS & SUPPLIES 
    \r\n\t\r\n\t\t\r\n\t
    \r\n\t
    \r\n\t
    INFORMATION 
    \r\n\t\r\n\t

    \r\n\t
    SERVICES 
    \r\n\t\r\n\r\n\t\t\r\n\t\t
    \r\n\t\t
    \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t
     
     \r\n\t\t\r\n \r\n \r\n\t\r\n \r\n\r\n\r\n\r\n\r\n\t\r\n
    \r\n\t\r\n\t\r\n\t\r\n \r\n \r\n
    \r\n\r\n
    \r\n\t\t\r\n
    \r\n\r\n
    Seeds & Supplies > Seeds > Vegetables > Onions
    \r\n\t\t\r\n\t\t\r\n\t\t
    Rossa Di Milano Onion
    \r\n\t\t\r\n\t\t\r\n
    \r\n\t\t

    \r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \"Item
    Rossa Di Milano Onion
    \r\n\t\t\t\tAlium cepa
    \r\nHeirloom/Rare
    \r\nHardy Biennial
    \r\n 
    \r\n\t\t\t\t

    (110-120 days)  Midsized Italian variety.  Long to intermediate day red onion that tolerates cool climates.  Excellent keeper.  We have grown out thousands of bulbs and re-selected this variety to be the top quality variety that it once was.  4-5" bulbs are top-shaped, uniformly colored, and have tight skins.

    \r\n\t\t\t\t\r\n\t\t\t\t

    SHOW THIS ITEM TO OTHERS ►

    \r\n\t\t\t\t
    Planting Depth: 3/4-1"
    \r\nSoil Temp. for Germ.: 50-85°F
    \r\nDays to Germ.: 3-8
    \r\nAvg. Spacing: 10-15 seeds/ft. in rows 12-18" apart
    \r\nAvg. Seeding Rate: 4-6 lbs./acre
    \r\nDays to Maturity: 110-120
    \r\nFull Sun
    \r\nWater Often
    \r\n 
    \r\n\t\t\t\t

    \r\n\t\t\r\n\t\t\r\n\t\t\t\r\n \t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n \r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \r\n
    \r\n
    \r\n
    Choose a Size:
    \r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Onion, Rossa Di Milano- Pack of 350
     
    Item#: 01585     Price: $3.49
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t
    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Rossa Di Milano Onion- Pack of 3500
     
    Item#: 06654     Price: $19.99
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Select \"Ship To\" Recipient:\r\n\t\t \r\n

    New Recipient Name:
    Enter the recipient's first name only. We'll ask for the recipient's full name and address later.

    \r\n
    \r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n \r\n \r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\r\n\t\t\t\t
     \r\n \r\n

    \r\n
    CONTINUE SHOPPING ►\r\n\t\t\t\t\t\t \r\n \r\n\t\t\t\t\t\t
    \r\n\t\t\t\t
    \r\n
    \r\n
    \r\n\t\t\r\n \r\n\r\n\t\r\n
    \r\n
    \r\n

    Supporting Sustainable Organic Agriculture Since 1989

    \r\n

    In 1989, Seeds of Change began with a simple mission: to preserve biodiversity and promote sustainable, organic agriculture. By cultivating and sharing an extensive range of organically grown vegetable, flower, herb and cover crop seeds, we have honored that mission for almost 25 years.

    \r\n
    \r\n\r\n
    \r\n\r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\t\r\n\t\t
     \r\n\t\t
    \r\n\t\t
    \r\n\t\t\t\t\t\r\n
    SEARCH
    \r\n\t\t\r\n\t\t \r\n\t\t \r\n\t\t\t\t\r\n\r\n\t\t
    \r\n\t\t\t\t \r\n\t\t\t\r\n\t\t\r\n \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n
    HOW TO ORDER
    Order Seeds Online
    Catalog Quick Order
    Contact Us

    FOLLOW US ON
    \r\n   
    Always certified organic
    \r\n\t\t\r\n\t\t\r\n\t\t
    \r\n\t \r\n\t\t\r\n\r\n\t\r\n\r\n\t\t\t\r\n\t\t\t
    \r\n\t\t
    \r\n\t\t
    \r\n\t\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n
    \r\n\t
    PRODUCTS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    GROWING TIPS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    CUSTOMER SERVICE
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n \r\n\t \r\n\t
    \r\n\t
    \r\n\r\n\r\n\r\n\r\n\r\n
    \r\n \r\n \r\n \r\n \r\n
    Shipping Info|Contact Us|Privacy Policy|Site Map|Organic Certification|Our Foods
    ®/TM Trademark © 2012 Seeds of Change..
    \r\n
    \r\n\r\n
    \r\n
    \r\n\r\n\r\n \r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", "scrapes": "default", "page_type": "item", "page_id": "4fad6a7c688f922437000014", "version": "0.13.0" }, { "extractors": {}, "annotated_body": "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\tSeeds of Change | Item Detail\r\n\r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n \r\n
    \r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\t\t\r\n\t\t\r\n\r\n\t\t\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n
      \r\n\r\n\r\n
    \r\nHOME|WHY ORGANIC?|DOWNLOAD A CATALOG|MY ACCOUNT|LOGIN\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n
    VIEW BASKET: 0 ITEMS($0.00)\r\n \r\n
    \r\n
    \r\n\r\n\r\n
      
    \r\n\t\t\r\n\t\t\t\r\n \r\n\r\n\r\n\r\n\r\n\r\n \r\n\t


    SEEDS & SUPPLIES 
    \r\n\t\r\n\t\t\r\n\t
    \r\n\t
    \r\n\t
    INFORMATION 
    \r\n\t\r\n\t

    \r\n\t
    SERVICES 
    \r\n\t\r\n\r\n\t\t\r\n\t\t
    \r\n\t\t
    \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t
     
     \r\n\t\t\r\n \r\n \r\n\t\r\n \r\n\r\n\r\n\r\n\r\n\t\r\n
    \r\n\t\r\n\t\r\n\t\r\n \r\n \r\n
    \r\n\r\n
    \r\n\t\t\r\n
    \r\n\r\n
    Seeds & Supplies > Seeds > Vegetables > Squash & Pumpkins > Winter Squash
    \r\n\t\t\r\n\t\t\r\n\t\t
    Gold Nugget
    \r\n\t\t\r\n\t\t\r\n
    \r\n\t\t

    \r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \"Product
    Gold Nugget
    \r\n\t\t\t\tCucurbita maxima
    \r\n
    Tender Annual
    \r\n 
    \r\n\t\t\t\t

    1-2 lbs. (75-95 days) This early, extremely productive, compact bush variety is ideal for small gardens.  Miniature pumpkin-shaped fruits have pale red-orange skin and dry, sweet, dark orange flesh.  Great for stuffing, soups and pies.

    \r\n\t\t\t\t\r\n\t\t\t\t

    SHOW THIS ITEM TO OTHERS ►

    \r\n\t\t\t\t
    Planting Depth: 1"
    \r\nSoil Temp. for Germ.: 70-90°F
    \r\nDays to Germ.: 7-10
    \r\nPlant Spacing: 3'-4'Apart
    \nDays to Maturity: 75-95
    \r\nFull Sun
    \r\nModerate Water
    \r\n 
    \r\n\t\t\t\t

    \r\n\t\t\r\n\t\t\r\n\t\t\t\r\n \t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n \r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \r\n
    \r\n
    \r\n
    Choose a Size:
    \r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Squash, Winter, Gold Nugget- Pack of 20
     
    Item#: 01593     Price: $3.49
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t
    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Gold Nugget Winter Squash- Pack of 250
     
    Item#: 06696     Price: $19.99
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Select \"Ship To\" Recipient:\r\n\t\t \r\n

    New Recipient Name:
    Enter the recipient's first name only. We'll ask for the recipient's full name and address later.

    \r\n
    \r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n \r\n \r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\r\n\t\t\t\t
     \r\n \r\n

    \r\n
    CONTINUE SHOPPING ►\r\n\t\t\t\t\t\t \r\n \r\n\t\t\t\t\t\t
    \r\n\t\t\t\t
    \r\n
    \r\n
    \r\n\t\t\r\n \r\n\r\n\t\r\n
    \r\n
    \r\n

    Supporting Sustainable Organic Agriculture Since 1989

    \r\n

    In 1989, Seeds of Change began with a simple mission: to preserve biodiversity and promote sustainable, organic agriculture. By cultivating and sharing an extensive range of organically grown vegetable, flower, herb and cover crop seeds, we have honored that mission for almost 25 years.

    \r\n
    \r\n\r\n
    \r\n\r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\t\r\n\t\t
     \r\n\t\t
    \r\n\t\t
    \r\n\t\t\t\t\t\r\n
    SEARCH
    \r\n\t\t\r\n\t\t \r\n\t\t \r\n\t\t\t\t\r\n\r\n\t\t
    \r\n\t\t\t\t \r\n\t\t\t\r\n\t\t\r\n \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n
    HOW TO ORDER
    Order Seeds Online
    Catalog Quick Order
    Contact Us

    FOLLOW US ON
    \r\n   
    Always certified organic
    \r\n\t\t\r\n\t\t\r\n\t\t
    \r\n\t \r\n\t\t\r\n\r\n\t\r\n\r\n\t\t\t\r\n\t\t\t
    \r\n\t\t
    \r\n\t\t
    \r\n\t\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n
    \r\n\t
    PRODUCTS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    GROWING TIPS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    CUSTOMER SERVICE
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n \r\n\t \r\n\t
    \r\n\t
    \r\n\r\n\r\n\r\n\r\n\r\n
    \r\n \r\n \r\n \r\n \r\n
    Shipping Info|Contact Us|Privacy Policy|Site Map|Organic Certification|Our Foods
    ®/TM Trademark © 2012 Seeds of Change..
    \r\n
    \r\n\r\n
    \r\n
    \r\n\r\n\r\n \r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", "url": "http://www.seedsofchange.com/garden_center/product_details.aspx?item_no=PS14165", "original_body": "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\tSeeds of Change | Item Detail\r\n\r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n \r\n
    \r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\t\t\r\n\t\t\r\n\r\n\t\t\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n
      \r\n\r\n\r\n
    \r\nHOME|WHY ORGANIC?|DOWNLOAD A CATALOG|MY ACCOUNT|LOGIN\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n
    VIEW BASKET: 0 ITEMS($0.00)\r\n \r\n
    \r\n
    \r\n\r\n\r\n
      
    \r\n\t\t\r\n\t\t\t\r\n \r\n\r\n\r\n\r\n\r\n\r\n \r\n\t


    SEEDS & SUPPLIES 
    \r\n\t\r\n\t\t\r\n\t
    \r\n\t
    \r\n\t
    INFORMATION 
    \r\n\t\r\n\t

    \r\n\t
    SERVICES 
    \r\n\t\r\n\r\n\t\t\r\n\t\t
    \r\n\t\t
    \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t
     
     \r\n\t\t\r\n \r\n \r\n\t\r\n \r\n\r\n\r\n\r\n\r\n\t\r\n
    \r\n\t\r\n\t\r\n\t\r\n \r\n \r\n
    \r\n\r\n
    \r\n\t\t\r\n
    \r\n\r\n
    Seeds & Supplies > Seeds > Vegetables > Squash & Pumpkins > Winter Squash
    \r\n\t\t\r\n\t\t\r\n\t\t
    Gold Nugget
    \r\n\t\t\r\n\t\t\r\n
    \r\n\t\t

    \r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \"Item
    Gold Nugget
    \r\n\t\t\t\tCucurbita maxima
    \r\n
    Tender Annual
    \r\n 
    \r\n\t\t\t\t

    1-2 lbs. (75-95 days) This early, extremely productive, compact bush variety is ideal for small gardens.  Miniature pumpkin-shaped fruits have pale red-orange skin and dry, sweet, dark orange flesh.  Great for stuffing, soups and pies.

    \r\n\t\t\t\t\r\n\t\t\t\t

    SHOW THIS ITEM TO OTHERS ►

    \r\n\t\t\t\t
    Planting Depth: 1"
    \r\nSoil Temp. for Germ.: 70-90°F
    \r\nDays to Germ.: 7-10
    \r\nPlant Spacing: 3'-4'Apart
    \r\nDays to Maturity: 75-95
    \r\nFull Sun
    \r\nModerate Water
    \r\n 
    \r\n\t\t\t\t

    \r\n\t\t\r\n\t\t\r\n\t\t\t\r\n \t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n \r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
    \r\n
    \r\n
    \r\n
    Choose a Size:
    \r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Squash, Winter, Gold Nugget- Pack of 20
     
    Item#: 01593     Price: $3.49
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t
    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\t\t\r\n\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Gold Nugget Winter Squash- Pack of 250
     
    Item#: 06696     Price: $19.99
       Quantity:  
    \r\n
    \r\n\t\t\t\t\r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
    Select \"Ship To\" Recipient:\r\n\t\t \r\n

    New Recipient Name:
    Enter the recipient's first name only. We'll ask for the recipient's full name and address later.

    \r\n
    \r\n\t\t\t\t

    \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n \r\n \r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t\r\n\t\t\t\t
     \r\n \r\n

    \r\n
    CONTINUE SHOPPING ►\r\n\t\t\t\t\t\t \r\n \r\n\t\t\t\t\t\t
    \r\n\t\t\t\t
    \r\n
    \r\n
    \r\n\t\t\r\n \r\n\r\n\t\r\n
    \r\n
    \r\n

    Supporting Sustainable Organic Agriculture Since 1989

    \r\n

    In 1989, Seeds of Change began with a simple mission: to preserve biodiversity and promote sustainable, organic agriculture. By cultivating and sharing an extensive range of organically grown vegetable, flower, herb and cover crop seeds, we have honored that mission for almost 25 years.

    \r\n
    \r\n\r\n
    \r\n\r\n\r\n\t\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\t\r\n\t\t
     \r\n\t\t
    \r\n\t\t
    \r\n\t\t\t\t\t\r\n
    SEARCH
    \r\n\t\t\r\n\t\t \r\n\t\t \r\n\t\t\t\t\r\n\r\n\t\t
    \r\n\t\t\t\t \r\n\t\t\t\r\n\t\t\r\n \r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n
    HOW TO ORDER
    Order Seeds Online
    Catalog Quick Order
    Contact Us

    FOLLOW US ON
    \r\n   
    Always certified organic
    \r\n\t\t\r\n\t\t\r\n\t\t
    \r\n\t \r\n\t\t\r\n\r\n\t\r\n\r\n\t\t\t\r\n\t\t\t
    \r\n\t\t
    \r\n\t\t
    \r\n\t\r\n\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n
    \r\n\t
    PRODUCTS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    GROWING TIPS
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t
    \r\n\t
    CUSTOMER SERVICE
    \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n\t \r\n \r\n\t \r\n\t
    \r\n\t
    \r\n\r\n\r\n\r\n\r\n\r\n
    \r\n \r\n \r\n \r\n \r\n
    Shipping Info|Contact Us|Privacy Policy|Site Map|Organic Certification|Our Foods
    ®/TM Trademark © 2012 Seeds of Change..
    \r\n
    \r\n\r\n
    \r\n
    \r\n\r\n\r\n \r\n\r\n\r\n
    \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", "scrapes": "default", "page_type": "item", "page_id": "4fad6a7d688f922437000017", "version": "0.13.0" } ], "start_urls": [ "http://www.seedsofchange.com/garden_center/browse_category.aspx?id=123" ], "name": "seedsofchange2", "exclude_patterns": [ "/tellafriend.aspx.+" ], "follow_patterns": [ "/garden_center/browse_category.aspx.+", "/garden_center/detailedCategoryDisplay.aspx.+", "/garden_center/product_details.aspx.+" ], "links_to_follow": "patterns", "respect_nofollow": true } ================================================ FILE: slybot/slybot/tests/data/SampleProject/spiders/sitemaps.json ================================================ { "templates": [ ], "start_urls": [ ], "exclude_patterns": [ ], "follow_patterns": [ ], "allowed_domains": [ "webupd8.org", "siliconrepublic.com" ], "links_to_follow": "patterns", "respect_nofollow": false } ================================================ FILE: slybot/slybot/tests/data/atom_sample.xml ================================================ Webupd8 Posts ================================================ FILE: slybot/slybot/tests/data/ebay_advanced_search.html ================================================ eBay Search: Advanced Search
    Skip to main content
    eBayAdvanced Search
    Advanced Search
    Sign in to see your favorite searches.Learn more.

    Find Items

      • See general search tips or using advanced search options
      •  
      • Search 

    • Search including

    • Price
    • Show items priced from $ to $

    • Buying formats

    • Show results
    • Listings
    • Number of bids from: to:
    • Multiple item listings from: to:
    • Learn more.
    • Learn more.
    • Learn more.
      • Shipping options

    • Location

    • Sellers

    • Sort by
    • View results
    • Results per page

    About eBay | Community | Announcements | Security Center | Buyer Tools | Policies | Stores | eBay Wish list | Site Map | eBay official time | Preview new features | Tell us what you think
    ================================================ FILE: slybot/slybot/tests/data/pinterest.html ================================================ Pinterest / Login

    ================================================ FILE: slybot/slybot/tests/data/rss_sample.xml ================================================ CarGurus: Alfa Romeo GT Updates http://www.cargurus.com/Cars/Alfa-Romeo-GT-Overview-d1100 Alfa Romeo GT Reviews, Discussions and Pictures Wed, 19 Dec 2012 13:37:17 GMT CarGurus.com 2012-12-19T13:37:17Z 2005 Alfa Romeo GT Review: An alternative choice and a good choice http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r177377 Beautiful car. Good economy from 1.9 litre turbo diesel engine, very refined cruiser <br />also than ... <a href="http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r177377">More</a><br /><br /><a href="http://www.cargurus.com/Cars/writeCarUserReview.action?entity=c10013">Driven a 2005 Alfa Romeo GT? Rate it!</a> Mon, 30 Jul 2012 22:56:59 GMT http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r177377 LSS_1265 2012-07-30T22:56:59Z 2007 Alfa Romeo GT Review: Best car I've ever owned! http://www.cargurus.com/Cars/2007-Alfa-Romeo-GT-Reviews-c10015#rid:r174050 I wanted a car that looks good and sporty, but needed the space to carry 2 <br />adults and 3 childr ... <a href="http://www.cargurus.com/Cars/2007-Alfa-Romeo-GT-Reviews-c10015#rid:r174050">More</a><br /><br /><a href="http://www.cargurus.com/Cars/writeCarUserReview.action?entity=c10015">Driven a 2007 Alfa Romeo GT? Rate it!</a> Thu, 03 Nov 2011 15:05:45 GMT http://www.cargurus.com/Cars/2007-Alfa-Romeo-GT-Reviews-c10015#rid:r174050 Matt922 2011-11-03T15:05:45Z 2004 Alfa Romeo GT Review: 2004 Alfa Romeo GT http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r154159 the Perforce on my car is amazing, the best is the handling it handles so well round the cornes and ... <a href="http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r154159">More</a><br /><br /><a href="http://www.cargurus.com/Cars/writeCarUserReview.action?entity=c10012">Driven a 2004 Alfa Romeo GT? Rate it!</a> Fri, 18 Jun 2010 14:47:16 GMT http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r154159 FXX_1051 2010-06-18T14:47:16Z 2005 Alfa Romeo GT Review: do you really want to drive an ugly but reliable c ... http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r148162 looks great, drives ok, reliability is rubbish. Like - the appearence, fuel ecconomy. <br />Hate - r ... <a href="http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r148162">More</a><br /><br /><a href="http://www.cargurus.com/Cars/writeCarUserReview.action?entity=c10013">Driven a 2005 Alfa Romeo GT? Rate it!</a> Sun, 21 Aug 2011 03:38:58 GMT http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r148162 Laurie101 2011-08-21T03:38:58Z 2007 Alfa Romeo GT Review: My Car http://www.cargurus.com/Cars/2007-Alfa-Romeo-GT-Reviews-c10015#rid:r143611 Makes the driver feel special, loads of low range torque, <br />quiet, reserved and great sound syst ... <a href="http://www.cargurus.com/Cars/2007-Alfa-Romeo-GT-Reviews-c10015#rid:r143611">More</a><br /><br /><a href="http://www.cargurus.com/Cars/writeCarUserReview.action?entity=c10015">Driven a 2007 Alfa Romeo GT? Rate it!</a> Mon, 25 Jan 2010 23:51:49 GMT http://www.cargurus.com/Cars/2007-Alfa-Romeo-GT-Reviews-c10015#rid:r143611 Thomas2104 2010-01-25T23:51:49Z 2004 Alfa Romeo GT Review: Bella Donna http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r97599 It's an Alfa Romeo. The only car I want more is a Maserati Granturismo<br /> * Performance – It' ... <a href="http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r97599">More</a><br /><br /><a href="http://www.cargurus.com/Cars/writeCarUserReview.action?entity=c10012">Driven a 2004 Alfa Romeo GT? Rate it!</a> Sat, 13 Dec 2008 00:41:52 GMT http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r97599 Martin44 2008-12-13T00:41:52Z 2005 Alfa Romeo GT Review: 100% Italian http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r97012 Quite simply the best looking car in its class/pricerange. The diesel purrs like a little kitten and ... <a href="http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r97012">More</a><br /><br /><a href="http://www.cargurus.com/Cars/writeCarUserReview.action?entity=c10013">Driven a 2005 Alfa Romeo GT? Rate it!</a> Wed, 03 Dec 2008 13:15:51 GMT http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013#rid:r97012 Chris13952 2008-12-03T13:15:51Z 2004 Alfa Romeo GT Review: love it http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r86476 fun car to drive, the performance is very good with a nice engine sound.<br />the car is gorgeous to ... <a href="http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r86476">More</a><br /><br /><a href="http://www.cargurus.com/Cars/writeCarUserReview.action?entity=c10012">Driven a 2004 Alfa Romeo GT? Rate it!</a> Tue, 19 Aug 2008 20:36:27 GMT http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012#rid:r86476 Stijn41 2008-08-19T20:36:27Z ================================================ FILE: slybot/slybot/tests/data/sitemap_sample.xml ================================================ https://www.siliconrepublic.com/post-sitemap1.xml 2003-06-04T10:46:42+01:00 https://www.siliconrepublic.com/post-sitemap2.xml 2004-02-11T12:29:08+00:00 https://www.siliconrepublic.com/post-sitemap3.xml 2004-09-10T09:48:13+01:00 ================================================ FILE: slybot/slybot/tests/data/templates/411_list.json ================================================ { "extractors": {}, "scrapes": "default", "version": "0.13.0", "name": "person-list", "plugins": { "annotations-plugin": { "extracts": [ { "tagid": 131, "container_id": "repeated", "id": "annotation1", "selector": "p.name", "data": { "1": { "extractors": [], "attribute": "content", "required": false, "field": "full_name" }, "2": { "extractors": [ "1" ], "attribute": "content", "required": false, "field": "first_name" }, "3": { "extractors": [ "2" ], "attribute": "content", "required": false, "field": "last_name" } }, "annotations": { "content": [ { "extractors": [], "attribute": "content", "required": false, "field": "full_name" }, { "extractors": [ "1" ], "attribute": "content", "required": false, "field": "first_name" }, { "extractors": [ "2" ], "attribute": "content", "required": false, "field": "last_name" } ] } }, { "tagid": 151, "container_id": "repeated", "id": "annotation2", "selector": "div.address", "data": { "1": { "extractors": [], "attribute": "content", "required": false, "field": "address" } }, "annotations": { "content": [ { "extractors": [], "attribute": "content", "required": false, "field": "address" } ] } }, { "item_container": true, "tagid": 126, "annotations": { "#portia-content": "#dummy" }, "repeated": true, "text-content": "#portia-content", "selector": ".serp-list-item", "id": "repeated", "container_id": "repeated#parent" }, { "item_container": true, "tagid": 125, "id": "repeated#parent", "text-content": "#portia-content", "selector": ".serp-list", "annotations": { "#portia-content": "#dummy" } } ] } }, "url": "http://www.411.com/name/joe-smith", "original_body": "\n\n \n \n Joe Smith | 411\n\n\n\n\n\n\n \n\n \n \n \n \n \n \n \n\n \n\n\n \n \n \n\n \n\n \n \n \n \n \n \n \n
    \n
    \n \n\n \n
    \n \n \n\n
    \n

    \n \n ×\n Search\n

    \n
    \n\n
    \n \n \n \n \n \n\n
    \n\n
    \n
    \n\n
    \n
    \n \n
    \n
    \n
    \n\n
    \n\n\n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n\n
    \n\n\n
    \n
    \n
    \n\n
    \n\n\n\n
    \n \n\n\n
    \n
    \n

    \n We found 100 exact matches for Joe Smith.\n

    \n\n
    \n \n
    \n
    \n \n
    \n\n
    \n \n
    \n\n
    \n\n
    \n Prev\n\n
      \n
    1. \n 1\n
    2. \n
    3. \n 2\n
    4. \n
    5. \n 3\n
    6. \n
    7. \n 4\n
    8. \n
    9. \n 5\n
    10. \n
    11. \n 6\n
    12. \n
    13. \n 7\n
    14. \n
    15. \n 8\n
    16. \n
    17. \n 9\n
    18. \n
    19. \n 10\n
    20. \n
    \n\n Next\n
    \n\n\n
    \n
    \n
    \n\n
    \n
    \n\n
    \n \n
    \n\n
    \n
    \n\n
    \n
    \n
    \n\n
    \n\n\n\n\n\n\n\n\n\n
    \n
    \n\n \n\n
    \n
    \n
    \n\n\n
    \n \n
    \n\n \n
    \n\n
    \n \n
    \n
    \n
    \n\n
    \n\n
    \n
    \n\n
    \n
    \n
    \n \"Upsell\n
    \n
    \n\n
    \n
    \n
    \n\n
    \n
    \n
    \n \n\n", "page_id": "1", "page_type": "item" } ================================================ FILE: slybot/slybot/tests/data/templates/autoevolution.html ================================================ Cars and Automakers Database - autoevolution

    Cars and Automakers Database

    tip:  try the car finder
    101 brands

    A

    8
    in production

    36
    discontinued

     

    7
    in production

    80
    discontinued

     

    3
    in production

    2
    discontinued

     

    0
    in production

    6
    discontinued

     

    18
    in production

    43
    discontinued

     

    59
    in production

    145
    discontinued

    B

    7
    in production

    27
    discontinued

     

    39
    in production

    145
    discontinued

     

    2
    in production

    20
    discontinued

     

    2
    in production

    3
    discontinued

     

    4
    in production

    26
    discontinued

     

    8
    in production

    33
    discontinued

    C

    16
    in production

    37
    discontinued

     

    7
    in production

    0
    discontinued

     

    56
    in production

    133
    discontinued

     

    5
    in production

    45
    discontinued

     

    21
    in production

    112
    discontinued

    D

    8
    in production

    27
    discontinued

     

    0
    in production

    30
    discontinued

     

    5
    in production

    17
    discontinued

     

    4
    in production

    0
    discontinued

     

    0
    in production

    1
    discontinued

     

    10
    in production

    50
    discontinued

     

    0
    in production

    1
    discontinued

     

    4
    in production

    0
    discontinued

    F

    12
    in production

    75
    discontinued

     

    36
    in production

    158
    discontinued

     

    1
    in production

    0
    discontinued

     

    53
    in production

    217
    discontinued

     

    0
    in production

    6
    discontinued

    G

    6
    in production

    0
    discontinued

     

    14
    in production

    28
    discontinued

     

    1
    in production

    0
    discontinued

    H

    3
    in production

    0
    discontinued

     

    18
    in production

    44
    discontinued

     

    30
    in production

    132
    discontinued

     

    0
    in production

    8
    discontinued

     

    32
    in production

    73
    discontinued

    I

    13
    in production

    32
    discontinued

     

    3
    in production

    13
    discontinued

    J

    11
    in production

    39
    discontinued

     

    10
    in production

    20
    discontinued

    K

    26
    in production

    41
    discontinued

     

    2
    in production

    8
    discontinued

     

    4
    in production

    0
    discontinued

    L

    5
    in production

    7
    discontinued

     

    8
    in production

    44
    discontinued

     

    5
    in production

    56
    discontinued

     

    8
    in production

    29
    discontinued

     

    17
    in production

    34
    discontinued

     

    11
    in production

    23
    discontinued

     

    4
    in production

    15
    discontinued

    M

    4
    in production

    0
    discontinued

     

    2
    in production

    0
    discontinued

     

    5
    in production

    4
    discontinued

     

    6
    in production

    19
    discontinued

     

    0
    in production

    36
    discontinued

     

    19
    in production

    62
    discontinued

     

    9
    in production

    3
    discontinued

     

    68
    in production

    342
    discontinued

     

    0
    in production

    15
    discontinued

     

    3
    in production

    15
    discontinued

     

    7
    in production

    11
    discontinued

     

    20
    in production

    79
    discontinued

     

    10
    in production

    5
    discontinued

    N

    46
    in production

    128
    discontinued

    O

    0
    in production

    16
    discontinued

     

    28
    in production

    106
    discontinued

    P

    2
    in production

    5
    discontinued

     

    1
    in production

    2
    discontinued

     

    3
    in production

    0
    discontinued

     

    29
    in production

    87
    discontinued

     

    0
    in production

    47
    discontinued

     

    48
    in production

    151
    discontinued

     

    8
    in production

    4
    discontinued

    Q

    4
    in production

    0
    discontinued

    R

    9
    in production

    9
    discontinued

     

    35
    in production

    139
    discontinued

     

    7
    in production

    20
    discontinued

    S

    1
    in production

    31
    discontinued

     

    0
    in production

    2
    discontinued

     

    3
    in production

    1
    discontinued

     

    4
    in production

    0
    discontinued

     

    0
    in production

    11
    discontinued

     

    5
    in production

    5
    discontinued

     

    20
    in production

    47
    discontinued

     

    17
    in production

    35
    discontinued

     

    9
    in production

    20
    discontinued

     

    5
    in production

    0
    discontinued

     

    6
    in production

    7
    discontinued

     

    14
    in production

    50
    discontinued

     

    16
    in production

    34
    discontinued

    T

    9
    in production

    3
    discontinued

     

    3
    in production

    3
    discontinued

     

    52
    in production

    149
    discontinued

     

    0
    in production

    14
    discontinued

    V

    20
    in production

    29
    discontinued

     

    58
    in production

    116
    discontinued

     

    12
    in production

    66
    discontinued

    W

    7
    in production

    4
    discontinued

    Z

    0
    in production

    6
    discontinued

    ================================================ FILE: slybot/slybot/tests/data/templates/autoevolution.json ================================================ { "extractors": {}, "id": "f608-48fc-9420", "name": "car", "original_body": "\n\n\nHONDA Civic 5 Doors (2005 - 2008)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t
    \n\t\t
    \n\t\t\t\t\t\t\n\t\t\t
    \n\t\t\t\tNews\n\t\t\t\tCars\n\t\t\t\tMoto\n\t\t\t\tReviews\n\t\t\t\tSpyshots\n\t\t\t\tGreen\n\t\t\t\t\t\t\t
    \n\t\t\t
    \n\t\t
    \n\t
    \n\t
    \n\t\t
    \n\t\t\t

    main topics:

    \n\t\t\tEDITORIAL\n\t\t\tCOVERSTORY\n\t\t\tAUTO SHOWS\n\t\t\tSTARS & CARS\n\t\t\tTUNING\n\t\t\tAUTO HOW-TO\n\t\t\tBAC CALCULATOR\n\t\t\t\n\t\t\tBMW\n\t\t\tTOYOTA\n\t\t\tMERCEDES\n\t\t\t... ▼\n\t\t
    \n\t\t
    \n\t\t\t

    don't miss:

    \n\t\t\tPHOTO OF THE DAY\n\t\t\tTECH TOYS\n\t\t\tSAFETY\n\t\t\tMOTORSPORT\n\t\t\tCAR FINDER\n\t\t\tMOTO HOW-TO\n\t\t\tGLOSSARY\n\t\t
    \n\t
    \n
    \n\t
    \n\t\t

    \"HONDA\" HONDA Civic 5 Doors 2005 - 2008

    \n\t\t\t\t\n\t\t\t
    \n\n\t\t
    \n\n\t\t
    \n\t\t\t
    \n\t\t\t\tIn 2005 Honda introduced the eighth generation Civic, with a different approach for the European market compared to the American/Japanese market. A year after it presented the Civic Concept, the production version rolled out, marking a staggering and unprecedented resemblance between the two. The car introduced a new and unconventional design inside and out. With the focus clearly on looks, Honda tried to answer complains of boring design from the previous generation and develop a compact addressed to a younger consumer segment. The engines behind the new Civic are both fuel efficient and thrifty with a 1.4-liter i-DSI, a 1.8-liter i-VTEC petrol unit and a 2.2-liter i-CTDi diesel.\t\t\t\t
    \n\t\t\t\t\tshare:      \n\t\t\t\t\t share\n\t\t\t\t\t share\n\t\t\t\t\t tweet\n\t\t\t\t
    \n\t\t\t\t

    see also:  \n\t\t\t\t\tphoto gallery\t\t\t\t\t\t\t\t\t\t\t\t\t\t

    \n\t\t\t
    \n\n\t\t\t\t\t\t
    \n\t\t\t\t\"HONDA\n\t\t\t\t\n\t\t\t\t
    13 photos
    \n\t\t\t
    \n\t\t\t\n\t\t\t
    \n\t\t
    \n\n\t\t\t\t

    Engines \"engines\"

    \n\n\t\t
    compare selected engine with:\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
    \n\n\t\t
    \n\t\t\t
    \n\t\t\t\t\t\t\t\t

    Gasoline engines

    \n\t\t\t\t\t
    • 1.4 i-DSI
    • 1.8 i-VTEC
    \n\t\t\t\t\t\t\t\t\t

    Diesel engines

    \n\t\t\t\t\t
    • 2.2 i-CTDi
    \n\t\t\t\t\t\t\t
    \n\n\t\t\t
    \n\t\t\t\t

    HONDA Civic 5 Doors 1.4 i-DSI - technical specs

    engine specifications

    Cylinders
    L4
    Displacement
    1339 cm3
    Power
    61 KW @ 5700 RPM
    83 HP @ 5700 RPM
    82 BHP @ 5700 RPM
    Torque
    87.8 lb-ft @ 2800 RPM
    119 Nm @ 2800 RPM
    Fuel System
    Multipoint Injection
    Fuel
    Gasoline
    CO2 Emissions
    139 g/km

    performance specifications

    Top Speed
    105.6 mph OR 170 km/h
    Acceleration 0-62 Mph (0-100 kph)
    14.6 s

    fuel consumption specifications

    City
    30.9 mpg US OR 7.6 L/100Km
    Highway
    48 mpg US OR 4.9 L/100Km
    Combined
    39.9 mpg US OR 5.9 L/100Km

    transmission specifications

    Drive Type
    Front Wheel Drive
    Gearbox
    Manual, 6 Speed

    brakes specifications

    Front
    Ventilated Discs
    Rear
    Discs

    tires specifications

    Tire Size
    205/55R16

    dimensions specifications

    Length
    167.3 in OR 4249 mm
    Width
    69.3 in OR 1760 mm
    Height
    57.5 in OR 1461 mm
    Front/rear Track
    59.1/59.4 in OR 1,501/1,509 mm
    Wheelbase
    103.9 in OR 2639 mm
    Ground Clearance
    -
    Cargo Volume
    17.1 cuFT OR 484 L
    Cd
    -

    weight specifications

    Unladen Weight
    2513.3 lbs OR 1140 kg
    Gross Weight Limit
    3637.6 lbs OR 1650 kg

    HONDA Civic 5 Doors 1.8 i-VTEC - technical specs

    engine specifications

    Cylinders
    L4
    Displacement
    1799 cm3
    Power
    103 KW @ 6300 RPM
    140 HP @ 6300 RPM
    138 BHP @ 6300 RPM
    Torque
    128.3 lb-ft @ 4300 RPM
    174 Nm @ 4300 RPM
    Fuel System
    Multipoint Injection
    Fuel
    Gasoline
    CO2 Emissions
    152 g/km

    performance specifications

    Top Speed
    127.4 mph OR 205 km/h
    Acceleration 0-62 Mph (0-100 kph)
    8.9 s

    fuel consumption specifications

    City
    28.7 mpg US OR 8.2 L/100Km
    Highway
    45.2 mpg US OR 5.2 L/100Km
    Combined
    36.8 mpg US OR 6.4 L/100Km

    transmission specifications

    Drive Type
    Front Wheel Drive
    Gearbox
    Manual, 6 Speed

    brakes specifications

    Front
    Ventilated Discs
    Rear
    Discs

    tires specifications

    Tire Size
    205/55R16

    dimensions specifications

    Length
    167.3 in OR 4249 mm
    Width
    69.3 in OR 1760 mm
    Height
    57.5 in OR 1461 mm
    Front/rear Track
    59.1/59.4 in OR 1,501/1,509 mm
    Wheelbase
    103.9 in OR 2639 mm
    Ground Clearance
    -
    Cargo Volume
    17.1 cuFT OR 484 L
    Cd
    -

    weight specifications

    Unladen Weight
    2568.4 lbs OR 1165 kg
    Gross Weight Limit
    3858.1 lbs OR 1750 kg

    HONDA Civic 5 Doors 2.2 i-CTDi - technical specs

    engine specifications

    Cylinders
    L4
    Displacement
    2204 cm3
    Power
    103 KW @ 4000 RPM
    140 HP @ 4000 RPM
    138 BHP @ 4000 RPM
    Torque
    250.8 lb-ft @ 2000 RPM
    340 Nm @ 2000 RPM
    Fuel System
    Common Rail
    Fuel
    Diesel
    CO2 Emissions
    135 g/km

    performance specifications

    Top Speed
    127.4 mph OR 205 km/h
    Acceleration 0-62 Mph (0-100 kph)
    8.6 s

    fuel consumption specifications

    City
    35.6 mpg US OR 6.6 L/100Km
    Highway
    54.7 mpg US OR 4.3 L/100Km
    Combined
    46.1 mpg US OR 5.1 L/100Km

    transmission specifications

    Drive Type
    Front Wheel Drive
    Gearbox
    Manual, 6 Speed

    brakes specifications

    Front
    Ventilated Discs
    Rear
    Discs

    tires specifications

    Tire Size
    205/55R16

    dimensions specifications

    Length
    167.3 in OR 4249 mm
    Width
    69.3 in OR 1760 mm
    Height
    57.5 in OR 1461 mm
    Front/rear Track
    59.1/59.4 in OR 1,501/1,509 mm
    Wheelbase
    103.9 in OR 2639 mm
    Ground Clearance
    -
    Cargo Volume
    17.1 cuFT OR 484 L
    Cd
    -

    weight specifications

    Unladen Weight
    2914.5 lbs OR 1322 kg
    Gross Weight Limit
    4166.7 lbs OR 1890 kg
    \t\t\t\t
    \n\t\t\t
    \n\n\t\t\t
    \n\t\t
    \n\t\t\n\t\t\n\t\t\t\t

    Photo Gallery

    \n\t\t
    \n\t\t

    exterior

      \"HONDA
      \"HONDA
      \"HONDA
      \"HONDA
      \"HONDA
      \"HONDA
      \"HONDA
      \"HONDA
      \"HONDA

    interior

      \"HONDA
      \"HONDA
      \"HONDA
      \"HONDA
    \t\t
    \n\t\t
    \n\t\t\n\t\t
    \n\t
    \n
    \n
    \n
    \n\t
    \n\t\tautoevolution\n\t\t
      \n\t\t\t
    • cars
    • \n\t\t\t
    • moto
    • \n\t\t\t
    • news
    • \n\t\t\t
    • reviews
    • \n\t\t\t
    • editorial
    • \n\t\t\t
    • coverstory
    • \n\t\t\t
    • auto how-to
    • \n\t\t\t
    • glossary
    • \n\t\t\t
    • car finder
    • \n\t\t\t
    • rss
    • \n\t\t
    \n\t\t

    \n\t\t\t© 2008-2016 SoftNews NET. All rights reserved. autoevolution® and the autoevolution® logo are registered trademarks.\n\t\t\tCopyright information\n\t\t\tPrivacy Policy\n\t\t\tTerms of Use\n\t\t\tContact Us\n\t\t

    \n\t
    \n
    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", "page_id": "f9595b583d2b1640b443722777d8225a9406bb80", "page_type": "item", "plugins": { "annotations-plugin": { "extracts": [ { "accept_selectors": [ ".content" ], "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "3573-47a6-9c1e", "item_container": true, "repeated": false, "schema_id": "3e48-4f1d-a25a", "selector": ".content", "text-content": "#portia-content" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > .grspec > dd:nth-child(2)" ], "container_id": "3573-47a6-9c1e", "data": { "5663-4902-92ef": { "attribute": "content", "extractors": {}, "field": "3d6c-406b-ada0", "required": false } }, "id": "1ca6-4f38-b451", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > .grspec > dd:nth-child(2)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > .grspec > dd:nth-child(4)" ], "container_id": "3573-47a6-9c1e", "data": { "35da-4a50-873d": { "attribute": "content", "extractors": {}, "field": "715d-44f0-8610", "required": false } }, "id": "ac64-4442-bcaa", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > .grspec > dd:nth-child(4)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > .grspec > dd:nth-child(10)" ], "container_id": "3573-47a6-9c1e", "data": { "a37e-4d0b-821a": { "attribute": "content", "extractors": {}, "field": "f875-47f9-b433", "required": false } }, "id": "712b-4ce9-aadb", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > .grspec > dd:nth-child(10)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > .grspec > dd:nth-child(12)" ], "container_id": "3573-47a6-9c1e", "data": { "c6ec-4034-854d": { "attribute": "content", "extractors": {}, "field": "7b14-4c51-9d8d", "required": false } }, "id": "fb80-48c1-bc5b", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > .grspec > dd:nth-child(12)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > .grspec > dd:nth-child(14)" ], "container_id": "3573-47a6-9c1e", "data": { "42d5-487f-bc4c": { "attribute": "content", "extractors": {}, "field": "5c91-4055-9cd0", "required": false } }, "id": "6729-4724-b57e", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > .grspec > dd:nth-child(14)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(4) > dd:nth-child(2)" ], "container_id": "3573-47a6-9c1e", "data": { "f633-4b45-b2a9": { "attribute": "content", "extractors": {}, "field": "2237-4b60-94ff", "required": false } }, "id": "303d-48a0-a8ff", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(4) > dd:nth-child(2)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(4) > dd:nth-child(4)" ], "container_id": "3573-47a6-9c1e", "data": { "13fe-404d-8cc2": { "attribute": "content", "extractors": {}, "field": "b12f-4593-bb1e", "required": false } }, "id": "12e0-445d-9cce", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(4) > dd:nth-child(4)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(6) > dd:nth-child(2)" ], "container_id": "3573-47a6-9c1e", "data": { "bad5-4796-8a59": { "attribute": "content", "extractors": {}, "field": "1bc1-4326-958c", "required": false } }, "id": "5ccb-4aa0-a9e9", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(6) > dd:nth-child(2)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(6) > dd:nth-child(4)" ], "container_id": "3573-47a6-9c1e", "data": { "c6db-4dc2-a7d5": { "attribute": "content", "extractors": {}, "field": "809c-4921-aaec", "required": false } }, "id": "a431-4d34-9839", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(6) > dd:nth-child(4)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(6) > dd:nth-child(6)" ], "container_id": "3573-47a6-9c1e", "data": { "0dfd-476d-9dc7": { "attribute": "content", "extractors": {}, "field": "74ca-4687-a998", "required": false } }, "id": "8fd4-45d2-a940", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(6) > dd:nth-child(6)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(12) > dd" ], "container_id": "3573-47a6-9c1e", "data": { "1dc7-44cc-8238": { "attribute": "content", "extractors": {}, "field": "de5d-4a74-bbbe", "required": false } }, "id": "886e-434b-b7cf", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(12) > dd" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(14) > dd:nth-child(2)" ], "container_id": "3573-47a6-9c1e", "data": { "3dc6-43c1-ae78": { "attribute": "content", "extractors": {}, "field": "ae56-4514-979d", "required": false } }, "id": "afb8-4b73-a408", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(14) > dd:nth-child(2)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(14) > dd:nth-child(4)" ], "container_id": "3573-47a6-9c1e", "data": { "ea8c-446b-a40e": { "attribute": "content", "extractors": {}, "field": "15f8-456a-b398", "required": false } }, "id": "5569-4726-9dce", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(14) > dd:nth-child(4)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(14) > dd:nth-child(6)" ], "container_id": "3573-47a6-9c1e", "data": { "606e-4a53-a71a": { "attribute": "content", "extractors": {}, "field": "81d2-4e34-afce", "required": false } }, "id": "bb8b-432a-9a83", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(14) > dd:nth-child(6)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(14) > dd:nth-child(8)" ], "container_id": "3573-47a6-9c1e", "data": { "c334-49ad-b939": { "attribute": "content", "extractors": {}, "field": "3848-45fc-8bbd", "required": false } }, "id": "1347-4b1f-999e", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(14) > dd:nth-child(8)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(14) > dd:nth-child(10)" ], "container_id": "3573-47a6-9c1e", "data": { "32d0-4928-8163": { "attribute": "content", "extractors": {}, "field": "c151-43ac-a996", "required": false } }, "id": "4e9b-48eb-9d3d", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(14) > dd:nth-child(10)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(14) > dd:nth-child(12)" ], "container_id": "3573-47a6-9c1e", "data": { "ce45-411d-a244": { "attribute": "content", "extractors": {}, "field": "edc5-44d4-8a37", "required": false } }, "id": "be26-4d19-95d5", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(14) > dd:nth-child(12)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(14) > dd:nth-child(14)" ], "container_id": "3573-47a6-9c1e", "data": { "b56c-4062-bbed": { "attribute": "content", "extractors": {}, "field": "97df-4068-b152", "required": false } }, "id": "e334-4bff-87d5", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(14) > dd:nth-child(14)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(16) > dd:nth-child(2)" ], "container_id": "3573-47a6-9c1e", "data": { "1a1f-4d4c-ab95": { "attribute": "content", "extractors": {}, "field": "eb01-487c-aabc", "required": false } }, "id": "901f-43ed-abf2", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(16) > dd:nth-child(2)" }, { "accept_selectors": [ "#eng_honda-civic-5-doors-2005-14-i-dsi > .enginedata > dl:nth-child(16) > dd:nth-child(4)" ], "container_id": "3573-47a6-9c1e", "data": { "b89f-47ed-a5ce": { "attribute": "content", "extractors": {}, "field": "cb72-40f4-be48", "required": false } }, "id": "a182-4128-95e2", "selector": ".content > .enginesbox > .fr > div:nth-child(1) > .enginedata > dl:nth-child(16) > dd:nth-child(4)" }, { "accept_selectors": [ ".modelphoto > a > img" ], "container_id": "3573-47a6-9c1e", "data": { "e246-499f-8ca9": { "attribute": "src", "extractors": {}, "field": "5a2c-4dde-a064", "required": false } }, "id": "e680-4782-9973", "selector": ".content > .modelbox > .modelphoto > a > img" }, { "accept_selectors": [ ".newstext" ], "container_id": "3573-47a6-9c1e", "data": { "43ea-4e95-9eea": { "attribute": "content", "extractors": {}, "field": "bf29-49d0-8d32", "required": false } }, "id": "cfeb-4ede-8028", "selector": ".content > .modelbox > .newstext" }, { "accept_selectors": [ "#li_eng_honda-civic-5-doors-2005-14-i-dsi", "#li_eng_honda-civic-5-doors-2005-18-i-vtec", "#li_eng_honda-civic-5-doors-2005-22-i-ctdi" ], "container_id": "3573-47a6-9c1e", "data": { "d036-4600-a8e2": { "attribute": "content", "extractors": {}, "field": "2dc2-45d8-9bfc", "required": false } }, "id": "1cd2-473f-9c04", "repeated": true, "selection_mode": "auto", "selector": ".content > .enginesbox > .fl > .list > .ellip" } ] } }, "scrapes": "3e48-4f1d-a25a", "spider": "www.autoevolution.com", "url": "http://www.autoevolution.com/cars/honda-civic-5-doors-2005.html#aeng_honda-civic-5-doors-2005-14-i-dsi", "version": "0.13.0b20", "results": [ { "fuel_effiency_city": [ "39.9 mpg US OR 5.9 L/100Km" ], "image": [ "http://s1.cdn.autoevolution.com/images/models/HONDA_Civic-5-Doors-2005_main.jpg" ], "cyclinders": [ "L4" ], "height": [ "59.1/59.4 in OR 1,501/1,509 mm" ], "_template": "f9595b583d2b1640b443722777d8225a9406bb80", "top_speed": [ "105.6 mph OR 170 km/h" ], "engines": [ "1.4 i-DSI", "1.8 i-VTEC", "2.2 i-CTDi" ], "fuel_type": [ "Gasoline" ], "fuel_efficiency": [ "30.9 mpg US OR 7.6 L/100Km" ], "width": [ "57.5 in OR 1461 mm" ], "unladen_weight": [ "2513.3 lbs OR 1140 kg" ], "total_length": [ "167.3 in OR 4249 mm" ], "?": [ "-" ], "fuel_effiency_highway": [ "48 mpg US OR 4.9 L/100Km" ], "_type": "car", "description": [ "In 2005 Honda introduced the eighth generation Civic, with a different approach for the European market compared to the American/Japanese market. A year after it presented the Civic Concept, the production version rolled out, marking a staggering and unprecedented resemblance between the two. The car introduced a new and unconventional design inside and out. With the focus clearly on looks, Honda tried to answer complains of boring design from the previous generation and develop a compact addressed to a younger consumer segment. The engines behind the new Civic are both fuel efficient and thrifty with a 1.4-liter i-DSI, a 1.8-liter i-VTEC petrol unit and a 2.2-liter i-CTDi diesel. share: \uf083 share \uf086 share \uf084 tweet see also: photo gallery" ], "engine_displacement": [ "1339 cm3" ], "f875-47f9-b433": [ "Multipoint Injection " ], "tyres": [ "205/55R16" ], "gross_weight": [ "3637.6 lbs OR 1650 kg" ], "0-100km/h": [ "14.6 s" ], "luggage": [ "17.1 cuFT OR 484 L" ], "url": "http://url", "wheelbase": [ "103.9 in OR 2639 mm" ], "length": [ "69.3 in OR 1760 mm" ], "emissions": [ "139 g/km" ] } ], "schemas": { "3e48-4f1d-a25a": { "name": "car", "fields": { "15f8-456a-b398": { "name": "length", "type": "text", "required": false, "vary": false }, "1bc1-4326-958c": { "name": "fuel_efficiency", "type": "text", "required": false, "vary": false }, "2dc2-45d8-9bfc": { "name": "engines", "type": "text", "required": false, "vary": false }, "3848-45fc-8bbd": { "name": "height", "type": "text", "required": false, "vary": false }, "5a2c-4dde-a064": { "name": "image", "type": "image", "required": false, "vary": false }, "5c91-4055-9cd0": { "name": "emissions", "type": "text", "required": false, "vary": false }, "81d2-4e34-afce": { "name": "width", "type": "text", "required": false, "vary": false }, "97df-4068-b152": { "name": "luggage", "type": "text", "required": false, "vary": false }, "b12f-4593-bb1e": { "name": "0-100km/h", "type": "text", "required": false, "vary": false }, "bf29-49d0-8d32": { "name": "description", "type": "text", "required": false, "vary": false }, "eb01-487c-aabc": { "name": "unladen_weight", "type": "text", "required": false, "vary": false }, "max_weight": { "name": "max_weight", "type": "text", "required": false, "vary": false }, "de5d-4a74-bbbe": { "name": "tyres", "type": "text", "required": false, "vary": false }, "edc5-44d4-8a37": { "type": "text", "required": false, "vary": false, "name": "?" }, "715d-44f0-8610": { "type": "text", "required": false, "vary": false, "name": "engine_displacement" }, "c151-43ac-a996": { "type": "text", "required": false, "vary": false, "name": "wheelbase" }, "cb72-40f4-be48": { "type": "text", "required": false, "vary": false, "name": "gross_weight" }, "74ca-4687-a998": { "type": "text", "required": false, "vary": false, "name": "fuel_effiency_city" }, "3d6c-406b-ada0": { "type": "text", "required": false, "vary": false, "name": "cyclinders" }, "ae56-4514-979d": { "type": "text", "required": false, "vary": false, "name": "total_length" }, "7b14-4c51-9d8d": { "type": "text", "required": false, "vary": false, "name": "fuel_type" }, "2237-4b60-94ff": { "type": "text", "required": false, "vary": false, "name": "top_speed" }, "809c-4921-aaec": { "type": "text", "required": false, "vary": false, "name": "fuel_effiency_highway" } } } } } ================================================ FILE: slybot/slybot/tests/data/templates/autoevolution2.json ================================================ { "annotated_body": "", "body": "original_body", "extractors": {}, "id": "2341-45eb-904a", "name": "FIAT Abarth Spider - - autoevolution", "original_body": "\n\n\n\n\n\n\nFIAT 124 Abarth Spider - 2017 - autoevolution\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n
    \n\n
    \n\t
    \n\t\t

    FIAT 124 Abarth Spider 2017 - Present

    \n\t\t
    Photo gallery (43)
    \"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT\"FIAT
    \t
    \n\n\t
    \n\t\t
    / Home / Cars / FIAT / 124 Abarth Spider
    \n\t
    \n\n\t
    \n\n\n\n\n\n
    \n
    \n\n\t
    \n\t\t
    Based on the reborn Fiat 124, the Abarth 124 Spider was gifted with more performance features in order to be the best driving machine the Italian house has to offer in 2016. First off, the looks have been altered to look fiercer through a new front grille, gaping lower intake, bigger rims, sport rear bumper with quad exhaust tips and a lip spoiler on the trunk. The interior got Alcantara trimmings, different seats and a contrast stitched steering wheel with a viewfinder. The engine makes more power, there's and optional automatic transmission on the list and the suspension has been modified a bit for sharper response.
    \n\n\t\t\t\t
    \n\t\t\t\n\t\t\t press release\n\t\t
    \n\t\t\t
    \n\n
    \n\n
    \n
    \n\n
    \n\t
    \n\t
      2 Gasoline engines
    • 1.4 6AT (170 HP)
    • 1.4 6MT (170 HP)
    \t
    \n\n\t\n\t
    compare
    \n\t

    Compare selected engine with...

    \n\t
    Pick brand
    • ACURA
    • ALFA ROMEO
    • ARIEL
    • ARO
    • ASTON MARTIN
    • AUDI
    • BENTLEY
    • BMW
    • BRISTOL
    • BUFORI
    • BUGATTI
    • BUICK
    • CADILLAC
    • CATERHAM
    • CHEVROLET
    • CHRYSLER
    • CITROEN
    • DACIA
    • DAEWOO
    • DAIHATSU
    • DATSUN
    • DMC
    • DODGE
    • DONKERVOORT
    • DR MOTOR
    • FERRARI
    • FIAT
    • FISKER
    • FORD
    • FSO
    • GEELY
    • GMC
    • GTA Motor
    • HINDUSTAN
    • HOLDEN
    • HONDA
    • HUMMER
    • HYUNDAI
    • INFINITI
    • ISUZU
    • JAGUAR
    • JEEP
    • KIA
    • KOENIGSEGG
    • KTM
    • LADA
    • LAMBORGHINI
    • LANCIA
    • LAND ROVER
    • LEXUS
    • LINCOLN
    • LOTUS
    • Mahindra
    • MARUSSIA
    • MARUTI SUZUKI
    • MASERATI
    • MAYBACH
    • MAZDA
    • MCLAREN
    • MERCEDES BENZ
    • MERCURY
    • MG
    • MINI
    • MITSUBISHI
    • MORGAN
    • NISSAN
    • OLDSMOBILE
    • OPEL
    • PAGANI
    • PANOZ
    • PERODUA
    • PEUGEOT
    • PONTIAC
    • PORSCHE
    • PROTON
    • QOROS
    • RAM Trucks
    • RENAULT
    • ROLLS-ROYCE
    • SAAB
    • SALEEN
    • SAMSUNG
    • SANTANA
    • SATURN
    • SCION
    • SEAT
    • SKODA
    • SMART
    • SPYKER
    • SSANGYONG
    • SUBARU
    • SUZUKI
    • TATA MOTORS
    • TESLA MOTORS
    • TOYOTA
    • TVR
    • VAUXHALL
    • VOLKSWAGEN
    • VOLVO
    • WIESMANN
    • ZENDER
    \t
    \n\n\t
    \n
    \n\n
    \n\t
    \n\t\t
    \n\t\t
    \n\t
    \n\t

    FIAT 124 Abarth Spider 1.4 6AT (170 HP)

    engine specifications  –  1.4 6AT (170 HP)
    Cylinders
    L4
    Displacement
    1368 cm3
    Power
    125.1 KW @ 5500 RPM
    170 HP @ 5500 RPM
    168 BHP @ 5500 RPM
    Torque
    184 lb-ft @ 2500 RPM
    250 Nm @ 2500 RPM
    Fuel System
    Turbocharged Multipoint Injection
    Fuel
    Gasoline
    CO2 Emissions
    153 g/km
    performance specifications
    Top Speed
    142 mph OR 229 km/h
    Acceleration 0-62 Mph (0-100 kph)
    6.9 s
    fuel consumption specifications
    City
    25.8 mpg US OR 9.1 L/100Km
    Highway
    45.2 mpg US OR 5.2 L/100Km
    Combined
    35.6 mpg US OR 6.6 L/100Km
    transmission specifications
    Drive Type
    Rear Wheel Drive
    Gearbox
    6-speed automatic
    brakes specifications
    Front
    Ventilated Discs
    Rear
    Discs
    tires specifications
    Tire Size
    205/45 R17 W84
    dimensions specifications
    Length
    159.6 in OR 4054 mm
    Width
    68.5 in OR 1740 mm
    Height
    48.5 in OR 1232 mm
    Front/rear Track
    58.9/59.2 in OR 1,496/1,504 mm
    Wheelbase
    90.9 in OR 2309 mm
    Ground Clearance
    4.7 in OR 119 mm
    Cargo Volume
    4.9 cuFT OR 139 L
    Cd
    -
    weight specifications
    Unladen Weight
    2381 lbs OR 1080 kg
    Gross Weight Limit
    -

    FIAT 124 Abarth Spider 1.4 6MT (170 HP)

    engine specifications  –  1.4 6MT (170 HP)
    Cylinders
    L4
    Displacement
    1368 cm3
    Power
    125.1 KW @ 5500 RPM
    170 HP @ 5500 RPM
    168 BHP @ 5500 RPM
    Torque
    184 lb-ft @ 2500 RPM
    250 Nm @ 2500 RPM
    Fuel System
    Turbocharged Multipoint Injection
    Fuel
    Gasoline
    CO2 Emissions
    148 g/km
    performance specifications
    Top Speed
    144 mph OR 232 km/h
    Acceleration 0-62 Mph (0-100 kph)
    6.8 s
    fuel consumption specifications
    City
    27.7 mpg US OR 8.5 L/100Km
    Highway
    46.1 mpg US OR 5.1 L/100Km
    Combined
    36.8 mpg US OR 6.4 L/100Km
    transmission specifications
    Drive Type
    Rear Wheel Drive
    Gearbox
    6-speed manual
    brakes specifications
    Front
    Ventilated Discs
    Rear
    Discs
    tires specifications
    Tire Size
    205/45 R17 W84
    dimensions specifications
    Length
    159.6 in OR 4054 mm
    Width
    68.5 in OR 1740 mm
    Height
    48.5 in OR 1232 mm
    Front/rear Track
    58.9/59.2 in OR 1,496/1,504 mm
    Wheelbase
    90.9 in OR 2309 mm
    Ground Clearance
    4.7 in OR 119 mm
    Cargo Volume
    4.9 cuFT OR 139 L
    Cd
    -
    weight specifications
    Unladen Weight
    2337 lbs OR 1060 kg
    Gross Weight Limit
    -
    \t  report a mistake on this page  \n\t
     
    \n
    \n
    \n\n\n
    \n
    \n\n
    \n

    © 2008-2016 SoftNews NET. All rights reserved. autoevolution® and the autoevolution® logo are registered trademarks.

    \n
    \n
    \n\n\n\n\n\n\n\n\n\n", "page_id": "", "page_type": "item", "plugins": { "annotations-plugin": { "extracts": [ { "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "0d9b-4cb8-89e5", "item_container": true, "repeated": false, "required": [], "schema_id": "9387-4bba-bf61", "selector": "#pagewrapper", "siblings": 1, "tagid": null, "text-content": "#portia-content" }, { "accept_selectors": [ ".seriestitle > a" ], "container_id": "0d9b-4cb8-89e5", "data": { "3828-4882-8cbb": { "attribute": "content", "extractors": {}, "field": "19b7-40f6-83df", "required": false } }, "id": "80cc-4979-bf27", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": false, "required": [], "selection_mode": "auto", "selector": "#pagewrapper > .clearfix > div:nth-child(1) > .seriestitle > a", "tagid": null, "xpath": "//*[@id=\"pagewrapper\"]/*[contains(concat(\" \", @class, \" \"), \" clearfix \")]/div[1]/*[contains(concat(\" \", @class, \" \"), \" seriestitle \")]/a" }, { "accept_selectors": [ "#eng_fiat-124-abarth-spider-2017-14-6at-170-hp > .enginedata > div:nth-child(1) > .grspec > dd:nth-child(2)", "#eng_fiat-124-abarth-spider-2017-14-6at-170-hp > .enginedata > div:nth-child(3) > .table1w > dd:nth-child(4)" ], "container_id": "0d9b-4cb8-89e5", "data": { "a681-4645-8fea": { "attribute": "content", "extractors": {}, "field": "0028-4c08-8b11", "required": false } }, "id": "4113-4f23-8708", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": true, "required": [], "selection_mode": "auto", "selector": "#pagewrapper > .container > .col123width > .col23width > div:nth-child(2) > .enginedata > .techdata > .table1w > dd", "tagid": null, "xpath": "//*[@id=\"pagewrapper\"]/*[contains(concat(\" \", @class, \" \"), \" container \")]/*[contains(concat(\" \", @class, \" \"), \" col123width \")]/*[contains(concat(\" \", @class, \" \"), \" col23width \")]/div[2]/*[contains(concat(\" \", @class, \" \"), \" enginedata \")]/*[contains(concat(\" \", @class, \" \"), \" techdata \")]/*[contains(concat(\" \", @class, \" \"), \" table1w \")]/dd" } ] } }, "schemas": { "9387-4bba-bf61": { "fields": { "1e52-4a32-aa5f": { "id": "1e52-4a32-aa5f", "name": "description", "required": false, "type": "text", "vary": false }, "19b7-40f6-83df": { "id": "19b7-40f6-83df", "name": "name", "required": false, "type": "text", "vary": false }, "3833-4fc1-a70d": { "id": "3833-4fc1-a70d", "name": "make", "required": false, "type": "text", "vary": false }, "c0de-45f7-808e": { "id": "c0de-45f7-808e", "name": "model", "required": false, "type": "text", "vary": false }, "ed65-4790-abfe": { "id": "ed65-4790-abfe", "name": "engine", "required": false, "type": "text", "vary": false }, "59d5-4c10-a2dc": { "id": "59d5-4c10-a2dc", "name": "cyclinders", "required": false, "type": "text", "vary": false }, "24f4-485d-8af6": { "id": "24f4-485d-8af6", "name": "displacement", "required": false, "type": "text", "vary": false }, "ca84-4bc4-a4e3": { "id": "ca84-4bc4-a4e3", "name": "power", "required": false, "type": "text", "vary": false }, "0028-4c08-8b11": { "id": "0028-4c08-8b11", "name": "info", "required": false, "type": "text", "vary": false } }, "name": "FIAT Abarth Spider - - autoevolution" } }, "results": [{ "_template": "2341-45eb-904a", "info": [ "L4", "1368 cm3", "125.1 KW @ 5500 RPM 170 HP @ 5500 RPM 168 BHP @ 5500 RPM Torque 184 lb-ft @ 2500 RPM 250 Nm @ 2500 RPM Fuel System Turbocharged Multipoint Injection", "Gasoline", "153 g/km", "142 mph OR 229 km/h", "6.9 s", "25.8 mpg US OR 9.1 L/100Km", "45.2 mpg US OR 5.2 L/100Km", "35.6 mpg US OR 6.6 L/100Km", "Rear Wheel Drive", "6-speed automatic", "Ventilated Discs", "Discs", "205/45 R17 W84", "159.6 in OR 4054 mm", "68.5 in OR 1740 mm", "48.5 in OR 1232 mm", "58.9/59.2 in OR 1,496/1,504 mm", "90.9 in OR 2309 mm", "4.7 in OR 119 mm", "4.9 cuFT OR 139 L", "-", "2381 lbs OR 1080 kg", "-" ], "_type": "FIAT Abarth Spider - - autoevolution", "url": "http://url", "name": [ "FIAT 124 Abarth Spider 2017 - Present" ] } ], "scrapes": "9387-4bba-bf61", "spider": "www.autoevolution.com", "url": "http://www.autoevolution.com/cars/fiat-124-abarth-spider-2017.html", "version": "0.13.0b23" } ================================================ FILE: slybot/slybot/tests/data/templates/cars.com.json ================================================ { "annotated_body": "", "body": "original_body", "extractors": {}, "id": "42a6-42fa-958e", "name": "1", "original_body": "\n\n\n\n \n \n \n \n \n \n \n \n \n \n 2016 Chevrolet Colorado Reviews, Specs and Prices | Cars.com\n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\n\n \n\n \n\n \n\n \n \n\n\n \n\n\n\n \n\n\n\n\n\n\n
    \n\n
    \n\n \n \n \n
      \n \n \n \n
    \n
      \n \n \n
    \n
      \n \n \n \n
    \n
    \n \n
      \n \n \n
    \n
      \n \n \n
    \n
    \n \n
      \n \n \n
    \n
      \n \n \n \n
    \n
    \n \n
      \n \n \n \n \n
    \n
      \n \n \n \n \n
    \n
      \n \n \n \n \n
    \n
    \n
    \n
    \n \n\n
    \n\n\n\n \n\n \n\n\n\n \n\n\n\n
    \n\n\n\n
    \n
    \n
    \n\n \n\n \n\n\n
    \n
    \n
    \n

    2016 Chevrolet Colorado

    \n \n\n Change Year\n \n
    \n

    Other Years

    \n \n
    \n
    \n
    \n
    \n \n \n \n \n \n 17 reviews\n
    \n\n\n\n
    \n
    \n \n
    \n
    \n\n \n\n
    \n
    \n \n
    \n
    \n\n
    \n\n
    \n
    \n \n View Gallery\n
    \n
    \n\n \n \n\n
    \n\n
    \n\n\n\n\n
    \n\n
    \n \n
    \n \n MSRP Range\n $20,055-$35,450\n \n\n Trims19\n\n Combined MPG 20-23 \n\n Seats 2-5 \n
    \n
    \n
    \n\n
    \n \n
    \n\n\n
    \n
    \n
    \n \n
    \n
    \n
    \n\n\n\n
    \n \n\n

    Our Take on the 2016 Chevrolet Colorado

    \n

    Our Take

    \n\n\n
    \n \n \n
    \n\n
    \n \n\n

    With the Chevrolet Colorado, which was new last year, GM is hoping to appeal to more pickup buyers by offering a smaller and more affordable truck that fits in a garage and can navigate narrow str... Read Full Report

    \n
    \n\n
    \n
    \n \n

    What We Like

    \n
      \n
    • Strong, balanced power (gas V-6 and diesel)
    • \n
    • Front-seat headroom
    • \n
    • Crew cab has adult-friendly backseat
    • \n
    • Connectivity and multimedia options
    • \n
    • Appealing base price
    • \n
    • Towing capability (diesel)
    • \n
    \n
    \n\n
    \n \n

    What We Don't Like

    \n
      \n
    • Sluggish acceleration (gas four-cylinder)
    • \n
    • Choppy two-wheel-drive ride
    • \n
    • Rough, long-throw manual transmission
    • \n
    • No automatic four-wheel-drive option
    • \n
    • Some cheap cabin materials
    • \n
    • Mediocre fuel economy (gas engines)
    • \n
    \n
    \n\n
    \n \n

    Notable Features

    \n
      \n
    • Turbo-diesel 2.8-liter four-cylinder (late availability)
    • \n
    • MyLink multimedia system with Apple CarPlay integration available
    • \n
    • Four-door crew- and extended-cab models
    • \n
    • Two cargo box lengths
    • \n
    • Forward collision alert, lane departure warning available
    • \n
    \n
    \n
    \n
    \n
    \n

    Reviews

    \n
    \n
    \n

    Our Expert Reviews

    \n
    \n \n
    \n \n
    \n \n
    \n
    \n
    \n

    With the addition of the powerful, efficient, beautifully integrated Duramax diesel powertrain, the 2016 Chevrolet Colorado becomes quite possibly the world's perfect pickup truck.The 2015 Chevrolet Colorado won our Best Pickup of 2015 award, and deservedly so — it's a fantastic combination of big-truck ability, useful interior technology and decent fuel economy all wrapped up i... Read Full Review

    \n Read All Expert Reviews\n\n \n \n \n
    \n\n
    \n \t

    Consumer Reviews

    \n
    \n \n

    4.5 out of 5

    \n

    Based on 17 reviews

    \n
    \n
    \n \n \n
    \n\n

    Best midsize truck available

    \n
    by PeteM143 from Mays Landing, NJ\n on September 4, 2016\n
    \n
    \n

    I just took delivery of my Colorado LT, 2.5 2wd, extended cab. I bought it out of state and drove it home across 6 states over 2 days. The trip allowed me to get familiar with the truck quickly and fr...\n \n Read Full Review\n \n

    \n
    \n\n \n
    \n\n\n\n
    \n
    \n\n
    \n

    19 Trims Available

    \n\n \n\n \n\n
    \n \n

    A trim is a style of a vehicle model. Each higher trim has different or upgraded features from the previous trim along with a price increase. Learn more about trims

    \n
    \n\n \u2028\n
    \n
    \n

    Trims Explained

    \n

    When talking about cars, “trims” is a way of differentiating between different versions of the same model. Typically, most start with a no-frills, or “base” trim, and as features are added, or a different engine, drivetrain (gas vs. hybrid, for example) or transmission are included, trim names change and prices go up. It’s important to carefully check the trims of the car you’re interested in to make sure that you’re getting the features you want, or that you’re not overpaying for features you don’t want.

    \n
    \n
    \n
    \n\n
    \n\n\n
    \n

    Safety

    \n\n
    \n

    Crash-Test Reports

    \n\n \n\n
    \n

    NHTSA Ratings

    \n

    Based on Chevrolet Colorado Base

    \n
    \n
    Overall
    \n
    \n \n \n
    \n
    Overall Front
    \n
    \n \n
    \n
    Overall Side
    \n
    \n \n \n
    \n
    Overall Rollover Rating
    \n
    \n \n \n
    \n
    \n\n \n\n \u2028\n
    \n \n
    \n
    \n

    NHTSA Ratings

    \n

    Based on Chevrolet Colorado Base

    \n
    \n
    \n
    Overall
    \n
    \n \n \n
    \n
    Overall Front
    \n
    \n \n \n
    \n\n
    Overall Side
    \n
    \n \n \n
    \n
    Overall Rollover Rating
    \n
    \n \n \n
    \n
    Driver's
    \n
    \n \n \n
    \n
    Passenger's
    \n
    \n \n \n
    \n
    Side Barrier
    \n
    \n \n \n
    \n
    Side Barrier Rating Driver
    \n
    \n \n \n
    \n
    Side Barrier Rating Passenger Rear Seat
    \n
    \n \n \n
    \n
    Side Pole
    \n
    \n \n \n
    \n
    Side Pole Barrier combined (Front)
    \n
    \n \n \n
    \n
    Side Pole Barrier combined (Rear)
    \n
    \n \n \n
    \n
    \n
    \n
    \n National Highway Traffic Safety Administration (NHTSA) is part of the U.S. Department of Transportation. NHTSA provides vehicle safety information such as front- and side-crash ratings and rollover ratings. Vehicles are rated using a star rating system from 1-5 stars, with 5 being the highest.\n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n

    Recalls

    \n
    \n\n\n

    \n There are currently 2 recalls for this car.\n

    \n\n\n
    \n \n

    Safety defects and recalls are relatively common. Stay informed and know what to do ahead of time.

    \n

    Safety defects and recalls explained

    \n
    \n
    \n
    \n\n
    \n\n
    \n\n
    \n
    \n\n\n
    \n

    Similar Models

    \n
    \n \n \n\n \n \n \n\n \n \n\n \n \n \n \n \n \n \n
    \n
    \n \n Compare Now\n
    \n
    \n\n \n\n\n

    You have selected maximum of 3 cars

    \n

    Remove one of these cars to add others or compare the below cars now.

    \n \n
    \n\n
    \n\n
    \n
    \n\n\t
    \n\t\t

    Other Years

    \n\t\t\n\t
    \n\n\n \n\n
    \n
    \n\n
    \n
    \n
    \n
    Our Company\n \n \n
    \n
    Our Company
    \n
    \n
    \n
    Our Partners\n \n \n
    \n
    Our Partners
    \n
    \n
    \n \n\n
    \n
    \n \n
    \n
    \n
    \n Powered By\n \n
    \n
    \n
    \n
    \n
    \n \n
    © 2015 Cars.com All rights\n reserved.\n
    \n
    \n
    \n
    \n\n
    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n\n\n\n\n\n\n\n\n\n\n\n
    \n\n\n\n", "page_id": "", "page_type": "item", "plugins": { "annotations-plugin": { "extracts": [ { "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "cf50-4056-8671", "item_container": true, "repeated": false, "required": [], "schema_id": "1ee7-4615-b85c", "selector": ".page-body > div:nth-child(2)", "siblings": 0, "tagid": null, "text-content": "#portia-content" }, { "accept_selectors": [ ".cui-alpha" ], "container_id": "cf50-4056-8671", "data": { "b83b-416f-84bb": { "attribute": "content", "extractors": {}, "field": "0c07-4bed-ba61", "required": false } }, "id": "2d82-4d78-82ad", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": false, "required": [], "selection_mode": "auto", "selector": ".page-body > div:nth-child(2) > .mmy-header > .mmy-header__title > .mmy-header__title-year > .cui-alpha", "tagid": null, "xpath": "//*[contains(concat(\" \", @class, \" \"), \" page-body \")]/div[2]/*[contains(concat(\" \", @class, \" \"), \" mmy-header \")]/*[contains(concat(\" \", @class, \" \"), \" mmy-header__title \")]/*[contains(concat(\" \", @class, \" \"), \" mmy-header__title-year \")]/*[contains(concat(\" \", @class, \" \"), \" cui-alpha \")]" }, { "accept_selectors": [ ".slide" ], "container_id": "cf50-4056-8671", "data": { "c2de-4937-88ab": { "attribute": "src", "extractors": {}, "field": "cbfc-472c-bd51", "required": false } }, "id": "01c0-41f9-a1f1", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": false, "required": [], "selection_mode": "auto", "selector": ".page-body > div:nth-child(2) > .mmy-header > .mmy-header__title > .mmy-carousel-dt > .module-container > .col-mb-12 > .scrollable-content-container > .scrollable-content > .cars-container > .hero-slider-wrapper > .hero-slider-clearfix > .slide", "tagid": null, "xpath": "//*[contains(concat(\" \", @class, \" \"), \" page-body \")]/div[2]/*[contains(concat(\" \", @class, \" \"), \" mmy-header \")]/*[contains(concat(\" \", @class, \" \"), \" mmy-header__title \")]/*[contains(concat(\" \", @class, \" \"), \" mmy-carousel-dt \")]/*[contains(concat(\" \", @class, \" \"), \" module-container \")]/*[contains(concat(\" \", @class, \" \"), \" col-mb-12 \")]/*[contains(concat(\" \", @class, \" \"), \" scrollable-content-container \")]/*[contains(concat(\" \", @class, \" \"), \" scrollable-content \")]/*[contains(concat(\" \", @class, \" \"), \" cars-container \")]/*[contains(concat(\" \", @class, \" \"), \" hero-slider-wrapper \")]/*[contains(concat(\" \", @class, \" \"), \" hero-slider-clearfix \")]/*[contains(concat(\" \", @class, \" \"), \" slide \")]" }, { "accept_selectors": [ ".mmy-info__msrp" ], "container_id": "cf50-4056-8671", "data": { "a0d5-4de3-97fb": { "attribute": "content", "extractors": {}, "field": "994b-4389-a6ac", "required": false } }, "id": "46c2-494c-a60c", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": false, "required": [], "selection_mode": "auto", "selector": ".page-body > div:nth-child(2) > .mmy-dashboard > div > .card > .mmy-info__msrp", "tagid": null, "xpath": "//*[contains(concat(\" \", @class, \" \"), \" page-body \")]/div[2]/*[contains(concat(\" \", @class, \" \"), \" mmy-dashboard \")]/div/*[contains(concat(\" \", @class, \" \"), \" card \")]/*[contains(concat(\" \", @class, \" \"), \" mmy-info__msrp \")]" } ] } }, "scrapes": "1ee7-4615-b85c", "spider": "www.cars.com", "url": "https://www.cars.com/research/chevrolet-colorado-2016/", "version": "0.13.0b20", "results": [ { "Image": [ "https://www.cstatic-images.com/car-pictures/xl/USC60CHT355A021001.png" ], "Title": [ "2016 Chevrolet Colorado" ], "_template": "42a6-42fa-958e", "_type": "Books", "price": [ "MSRP Range $ 20,055 - $35,450" ], "url": "http://url" } ], "schemas": { "1ee7-4615-b85c": { "fields": { "b155-4aa8-a992": { "id": "b155-4aa8-a992", "name": "1", "required": false, "type": "text", "vary": false }, "c1e3-413a-8ba2": { "id": "c1e3-413a-8ba2", "name": "field2", "required": false, "type": "price", "vary": false }, "0c07-4bed-ba61": { "auto_created": true, "id": "0c07-4bed-ba61", "name": "Title", "required": false, "type": "text", "vary": false }, "cbfc-472c-bd51": { "auto_created": true, "id": "cbfc-472c-bd51", "name": "Image", "required": false, "type": "image", "vary": false }, "994b-4389-a6ac": { "auto_created": true, "id": "994b-4389-a6ac", "name": "price", "required": false, "type": "text", "vary": false } }, "name": "Books" } } } ================================================ FILE: slybot/slybot/tests/data/templates/cars.com_nested.json ================================================ { "body": "original_body", "id": "9342-43b3-a5a5", "name": "GMC Acadia Reviews Specs and Prices Carscom", "original_body": "\n\n\n\n \n \n \n \n \n \n \n \n \n 2016 GMC Acadia Reviews, Specs and Prices | Cars.com\n \n \n \n \n\n \n\n \n \n\n\n \n\n \n\n \n \n\n\n \n\n\n\n \n\n\n \n \n \n\n \n \n \n \n\n\n\n\n\n\n \n \n\n
    \n\n
    \n\n \n \n \n
      \n \n \n \n
    \n
      \n \n \n
    \n
      \n \n \n \n
    \n
    \n \n
      \n \n \n
    \n
      \n \n \n
    \n
    \n \n
      \n \n \n
    \n
      \n \n \n \n
    \n
    \n \n
      \n \n \n \n \n
    \n
      \n \n \n \n \n
    \n
      \n \n \n \n \n
    \n
    \n
    \n
    \n \n\n
    \n\n\n\n \n\n \n\n\n\n \n\n\n\n
    \n\n\n\n
    \n
    \n
    \n\n \n\n \n\n
    \n
    \n
    \n

    2016 GMC Acadia

    \n \n\n Change Year\n
    \n
    \n \n \n \n \n \n 8 reviews\n
    \n\n\n
    \n Best Bet\n
    \n\n
    \n
    \n \n
    \n
    \n\n \n\n
    \n
    \n \n
    \n
    \n\n
    \n\n
    \n
    \n \n Photos\n \n
    \n
    \n\n \n \n\n
    \n
    \n\n\n\n\n\n\n
    \n

    Other Years

    \n \n
    \n
    \n\n
    \n\n
    \n \n
    \n \n MSRP Range\n $30,975-$49,890\n \n\n Trims11\n\n Combined MPG 18 \n\n Seats 7-8 \n
    \n
    \n
    \n\n\n
    \n
    \n
    \n \n Test Drive\n \n
    \n
    \n
    \n\n\n\n
    \n \n\n

    Our Take on the 2016 GMC Acadia

    \n

    Our Take

    \n\n
    \n Best Bet\n View Our Criteria\n \n
    \n\n
    \n \n \n
    \n\n
    \n \n\n

    The GMC Acadia is a full-size crossover SUV that is related to the Chevrolet Traverse and Buick Enclave. It's available with front- or all-wheel drive and can seat seven or eight people. Competitors include the Ford Explorer, Mazda CX-9 and Honda Pilot. The standard OnStar communication sys... Read Full Report

    \n
    \n\n
    \n
    \n \n

    What We Like

    \n
      \n
    • Carlike ride and handling
    • \n
    • Cargo space
    • \n
    • Roomy second row
    • \n
    • Backup camera standard
    • \n
    \n
    \n\n
    \n \n

    What We Don't Like

    \n
      \n
    • Cramped third row
    • \n
    • Touch-screen too small
    • \n
    • Large turning circle
    • \n
    • Hulking size hurts maneuverability
    • \n
    \n
    \n\n
    \n \n

    Notable Features

    \n
      \n
    • OnStar 4G LTE connectivity and Wi-Fi hot spot
    • \n
    • Seats seven or eight
    • \n
    • Front- or all-wheel drive
    • \n
    • Airbag between front seats available
    • \n
    • Forward collision alert, lane departure warning available
    • \n
    \n
    \n
    \n
    \n
    \n

    Reviews

    \n
    \n \n
    \n \t

    Consumer Reviews

    \n
    \n \n 4.8\n

    Average based on 8 reviews

    \n
    \n
    \n \n \n
    \n\n

    Best vehicle for my family

    \n
    by shon from Seminole, FL\n on March 31, 2016\n
    \n
    \n

    My husband & I got thid vehicle less than a year ago, this is by far the best for us & the kids. Very spacious for a large family, still learning to use all the new technologies. Great on gas, alot of...\n \n Read Full Review\n \n

    \n
    \n\n \n
    \n\n\n
    \n
    \n\n
    \n

    11 Trims Available

    \n\n \n\n \n\n
    \n \n

    A trim is a style of a vehicle model. Each higher trim has different or upgraded features from the previous trim along with a price increase.\n Learn more about trims\n

    \n
    \n\n \u2028\n
    \n
    \n

    Trims Explained

    \n

    When talking about cars, \u201ctrims\u201d is a way of differentiating between different versions of the same model. Typically, most start with a no-frills, or \u201cbase\u201d trim, and as features are added, or a different engine, drivetrain (gas vs. hybrid, for example) or transmission are included, trim names change and prices go up.

    \n
    \n

    It\u2019s important to carefully check the trims of the car you\u2019re interested in to make sure that you\u2019re getting the features you want, or that you\u2019re not overpaying for features you don\u2019t want.

    \n
    \n
    \n
    \n\n
    \n\n
    \n\t

    Gallery

    \n\t
    \n\t\t
    \n\t\t\t\n
    \n\t\t
    \n\t\t
    \n\t\t\t\n
    \n\t\t
    \n\t\t
    \n\t\t\t\n
    \n\t\t
    \n\t\t
    \n\t\t\t\n
    \n\t\t
    \n\t\t
    \n\t\t\t\n
    \n\t\t
    \n\t\t
    \n\t\t\t\n
    \n\t\t\t\t+9\n\t\t
    \n\t
    \n
    \n\n\n\n
    \n

    Safety

    \n\n
    \n

    Crash-Test Reports

    \n\n
    \n

    IIHS Ratings

    \n

    Based on GMC Acadia Denali

    \n
    \n
    Head Restraints and Seats
    \n
    \n G\n \n
    \n
    Moderate overlap front
    \n
    \n G\n \n
    \n
    Roof Strength
    \n
    \n G\n \n
    \n
    Side
    \n
    \n G\n \n
    \n
    \n\n \n\n \n

    IIHS Ratings

    \n\t\t\t

    Based on GMC Acadia Denali

    \n
    \n\t\t\t\t
    \n\t\t\t\t\tG\n\t\t\t\t\tGood\n\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\tA\n\t\t\t\t\tAcceptable\n\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\tM\n\t\t\t\t\tMarginal\n\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\tP\n\t\t\t\t\tPoor\n\t\t\t\t
    \n\t\t\t
    \n\n

    Child Seat Anchors (Latch)

    \n
    \n
    Ease of Use
    \n
    \n M\n \n
    \n
    \n

    Head Restraints and Seats

    \n
    \n
    Dynamic Rating
    \n
    \n G\n \n
    \n
    Overall Rear
    \n
    \n G\n \n
    \n
    Seat Head/Restraint Geometry
    \n
    \n G\n \n
    \n
    \n

    Moderate overlap front

    \n
    \n
    Chest
    \n
    \n G\n \n
    \n
    Head/Neck
    \n
    \n G\n \n
    \n
    Left Leg/Foot
    \n
    \n G\n \n
    \n
    Overall Front
    \n
    \n G\n \n
    \n
    Restraints
    \n
    \n G\n \n
    \n
    Right Leg/Foot
    \n
    \n G\n \n
    \n
    Structure/safety cage
    \n
    \n G\n \n
    \n
    \n

    Other

    \n
    \n
    Roof Strength
    \n
    \n G\n \n
    \n
    \n

    Side

    \n
    \n
    Driver Head Protection
    \n
    \n G\n \n
    \n
    Driver Head and Neck
    \n
    \n G\n \n
    \n
    Driver Pelvis/Leg
    \n
    \n G\n \n
    \n
    Driver Torso
    \n
    \n G\n \n
    \n
    Overall Side
    \n
    \n G\n \n
    \n
    Rear Passenger Head Protection
    \n
    \n G\n \n
    \n
    Rear Passenger Head and Neck
    \n
    \n G\n \n
    \n
    Rear Passenger Pelvis/Leg
    \n
    \n G\n \n
    \n
    Rear Passenger Torso
    \n
    \n G\n \n
    \n
    Structure/safety cage
    \n
    \n G\n \n
    \n
    \n\n\t\t\t
    \n\t\t\t\tInsurance Institute for Highway Safety (IIHS) is a nonprofit research and communications organization funded by auto insurers. IIHS rates vehicles good, acceptable, marginal or poor based on performance in high-speed front and side crash tests. IIHS also evaluates seat/head restraints for protection against neck injuries in rear impacts.\n\t\t\t
    \n
    \n
    \n\n\n
    \n

    NHTSA Ratings

    \n

    Based on GMC Acadia Denali

    \n
    \n
    Overall
    \n
    \n \n \n
    \n
    Overall Front
    \n
    \n \n
    \n
    Overall Side
    \n
    \n \n \n
    \n
    Overall Rollover Rating
    \n
    \n \n \n
    \n
    \n\n \n\n \u2028\n
    \n\n
    \n
    \n

    NHTSA Ratings

    \n

    Based on GMC Acadia Denali

    \n
    \n
    \n
    Overall
    \n
    \n \n \n
    \n
    Overall Front
    \n
    \n \n \n
    \n\n
    Overall Side
    \n
    \n \n \n
    \n
    Overall Rollover Rating
    \n
    \n \n \n
    \n
    Driver's
    \n
    \n \n \n
    \n
    Passenger's
    \n
    \n \n \n
    \n
    Side Barrier
    \n
    \n \n \n
    \n
    Side Barrier Rating Driver
    \n
    \n \n \n
    \n
    Side Barrier Rating Passenger Rear Seat
    \n
    \n \n \n
    \n
    Side Pole
    \n
    \n \n \n
    \n
    Side Pole Barrier combined (Front)
    \n
    \n \n \n
    \n
    Side Pole Barrier combined (Rear)
    \n
    \n \n \n
    \n
    \n
    \n
    \n National Highway Traffic Safety Administration (NHTSA) is part of the U.S. Department of Transportation. NHTSA provides vehicle safety information such as front- and side-crash ratings and rollover ratings. Vehicles are rated using a star rating system from 1-5 stars, with 5 being the highest.\n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n

    Recalls

    \n
    \n\n\n

    \n There are currently 2 recalls for this car.\n

    \n\n\n
    \n \n

    Safety defects and recalls are relatively common. Stay informed and know what to do ahead of time.

    \n

    Safety defects and recalls explained

    \n
    \n
    \n
    \n\n
    \n\n
    \n\n
    \n
    \n\n\n
    \n

    Similar Models

    \n

    Select up to three models to compare with the 2016 GMC Acadia

    \n \n
    \n\n\t
    \n\t\t

    Other Years

    \n\t\t\n\t
    \n\n\n \n\n
    \n
    \n\n
    \n
    \n
    \n
    Our Company\n \n \n
    \n
    Our Company
    \n
    \n
    \n
    Our Partners\n \n \n
    \n
    Our Partners
    \n
    \n
    \n \n\n
    \n
    \n \n
    \n
    \n
    \n Powered By\n \n
    \n
    \n
    \n
    \n
    \n \n
    © 2016 Cars.com All rights\n reserved.\n
    \n
    \n
    \n
    \n\n
    \n \n\n \n\n\n\n\n\n \n\n\n \n \n \n\n \n \n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n\n\n\n", "page_id": "", "page_type": "item", "plugins": { "annotations-plugin": { "extracts": [ { "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "99d8-4e55-b46d", "item_container": true, "repeated": false, "required": [], "schema_id": "8b0c-44a1-9f45", "selector": ".page-body > div:nth-child(2)", "siblings": 0, "tagid": null, "text-content": "#portia-content" }, { "annotations": { "#portia-content": "#dummy" }, "container_id": "99d8-4e55-b46d", "field": "subitem1", "id": "bc5a-4d37-82a7", "item_container": true, "repeated": false, "required": [], "schema_id": "4bc8-4b9a-95a1", "selector": ".page-body > div:nth-child(2)", "siblings": 0, "tagid": null, "text-content": "#portia-content" }, { "accept_selectors": [ "em:nth-child(3)" ], "container_id": "bc5a-4d37-82a7", "data": { "e9ab-490d-9f16": { "attribute": "content", "extractors": {}, "field": "8a86-4a96-a035", "required": false } }, "id": "4684-449a-8fbc", "selection_mode": "auto", "selector": ".page-body > div:nth-child(2) > .mmy-dashboard > div > .card > .mmy-info__msrp > em:nth-child(3)" }, { "accept_selectors": [ ".cui-alpha" ], "container_id": "bc5a-4d37-82a7", "data": { "2a98-487f-b4f3": { "attribute": "content", "extractors": {}, "field": "b6e1-4281-ae27", "required": false } }, "id": "4508-4a5e-851e", "selection_mode": "auto", "selector": ".page-body > div:nth-child(2) > .mmy-header > .mmy-header__title > .mmy-header__title-year > .cui-alpha" }, { "accept_selectors": [ "b:nth-child(2)" ], "container_id": "99d8-4e55-b46d", "data": { "9980-4049-8333": { "attribute": "content", "extractors": {}, "field": "7148-4450-9df2", "required": false } }, "id": "d227-4cad-84a2", "selection_mode": "auto", "selector": ".page-body > div:nth-child(2) > .mmy-header > .mmy-header__title > .mmy-header__gallery > .gallery__link > .gallery__link-icon > b" }, { "accept_selectors": [ ".rating-link" ], "container_id": "99d8-4e55-b46d", "data": { "225f-4df5-a82d": { "attribute": "content", "extractors": {}, "field": "b04c-4fe6-9c2d", "required": false } }, "id": "d315-4193-8a5d", "selection_mode": "auto", "selector": ".page-body > div:nth-child(2) > .mmy-header > .mmy-header__title > .mmy-header__stars > .rating-link" }, { "accept_selectors": [ ".photo-wrapper:nth-child(1) > img" ], "container_id": "99d8-4e55-b46d", "data": { "20f9-4af9-8194": { "attribute": "src", "extractors": {}, "field": "e9b1-4b01-b628", "required": false } }, "id": "8d9f-4fd2-a876", "selection_mode": "auto", "selector": ".page-body > div:nth-child(2) > .mmy-gallery > .gallery-module > div:nth-child(1) > img" } ] } }, "schemas": { "4bc8-4b9a-95a1": { "fields": { "55f0-4671-89e5": { "id": "55f0-4671-89e5", "name": "field1", "required": false, "type": "text", "vary": false }, "0084-480e-99f1": { "id": "0084-480e-99f1", "name": "field2", "required": false, "type": "text", "vary": false }, "be49-4d40-92a3": { "id": "be49-4d40-92a3", "name": "field3", "required": false, "type": "text", "vary": false }, "b16a-4cdd-a995": { "auto_created": true, "id": "b16a-4cdd-a995", "name": "field4", "required": false, "type": "text", "vary": false }, "8a86-4a96-a035": { "auto_created": true, "id": "8a86-4a96-a035", "name": "price", "required": false, "type": "text", "vary": false }, "b6e1-4281-ae27": { "auto_created": true, "id": "b6e1-4281-ae27", "name": "title", "required": false, "type": "text", "vary": false } }, "name": "123" }, "8b0c-44a1-9f45": { "fields": { "7148-4450-9df2": { "id": "7148-4450-9df2", "name": "photos", "required": false, "type": "text", "vary": false }, "b04c-4fe6-9c2d": { "id": "b04c-4fe6-9c2d", "name": "review", "required": false, "type": "text", "vary": false }, "e9b1-4b01-b628": { "id": "e9b1-4b01-b628", "name": "image", "required": false, "type": "image", "vary": false } }, "name": "GMC Acadia Reviews Specs and Prices Carscom" } }, "scrapes": "", "results": [{ "_template": "9342-43b3-a5a5", "_type": "GMC Acadia Reviews Specs and Prices Carscom", "image": [ "http://www.cstatic-images.com/stock/900x600/1434993474945.jpg" ], "photos": [ "15" ], "review": [ "8 reviews" ], "subitem1": { "_type": "123", "price": [ "30,975" ], "title": [ "2016 GMC Acadia" ] }, "url": "http://url" }], "url": "https://www.cars.com/research/gmc-acadia-2016/", "version": "0.13.0b28" } ================================================ FILE: slybot/slybot/tests/data/templates/cs-cart.json ================================================ { "extractors": {}, "id": "e1bb-4478-9995", "name": "electronics-cameras-photo-camcorders-compact", "original_body": "\n\n\n\nElectronics :: Cameras & Photo :: Camcorders :: Compact Full HD Camcorder\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n \n \n\n\n

    Demo store panel

    Demo will be reset in: minute(s)Go to Administration panel
    \n \n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n \n \n \n
    \n
    \n \n\n\n
    \n
    \n
    \n\n
    \n $\n \n £\n
    \n
    \n \n \n ($)\n \n \n\n
    \n \n
    \n
    \n \n
    \n\n
    \n
    \n \n\n\n
    \n
    \n
    \n \n \n\n \n\n
    \n
    \n \n\n
    \n \n\n \n \n \n
    \n\n
    \n
    \n \n \n\n \n \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n \n\n\n
    \n
    \n
    \n \n \"\"\n \n
    \n
    \n
    \n \n\n\n
    \n
    \n
    \n
    \n \n \n \n \n \n \n \n\n \n\n\n \n\n \n
    \n
    \n\n\n
    \n
    \n \n\n\n
    \n
    \n
    8(800)-000-00-00
    \n
    \n \nRequest call\n\n
    \n \n
    \n\n
    \n
    \n
    \n \n\n\n
    \n
    \n \n
    \n \n
    \n \n
    \n
    \n
    Cart is empty
    \n
    \n\n
    \n
    \n View cart\n
    \n
    \n Checkout\n
    \n
    \n \n
    \n \n\n
    \n
    \n\n\n\n
    \n
    \n
    \n\n\n
    \n \n
    \n
    \n
    \n
    \n\n
    \n
    \n \n\n\n
    \n
    \n\n
    \n Home/Electronics/Cameras & Photo/Camcorders/Compact Full HD Camcorder\t
    \n\t \n\t 1\n\t of\n\t 12\n\t \n\t
    \n\n
    \n
    \n
    \n
    \n\n\n
    \n \n
    \n
    \n
    \n \n \n \n\n
    \n \n \n \n
    \n\n
    \n \n \n
    \n\n \n\n\n
    \n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n \n
    \n\n \n Save 10%\n \n \n\n \n \n \n \n
    \n\"\"\n\n\n \n \n \n \n \n \n
    \n\n \n \n\n\n\n\n\n\n\n\n\n
    \n \n\n
    \n
    \n
    \n\n\n\n\n\n \n

    Compact Full HD Camcorder

    \n \n \n
    \n \n\n \n
    \n \n\n \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n\n \n\n\n\n 1 review\n Write a review\n
    \n\n\n \n \n
    \n

    FREE US shipping over $100!Orders within next 2 days will be shipped on Monday

    \n
    \n \n\n\n
    \n
    \n \n \n List price: $334.00\n \n\n \n \n
    \n \n \n \n \n $299.99\n \n\n \n\n
    \n \n \n \n \n \n You save: $34.01 (10%)\n \n \n
    \n
    \n\n
    \n
    \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\n\n \n\n
    \n \n
    \n \n
    \n
    \n \n \n \n\n
    \n Price in points:\n 300 points\n
    \n
    \n Reward points:\n points\n
    \n\n
    \n \n
    \n\n
    \n
    \n \n \n Y0172YCAWT\n
    \n \n
    \n\n
    \n \n
    \n \n
    \n \n In stock\n
    \n
    \n\n\n\n\n \n
    \n \n \n \n
    \n
    \n +\n \n \n
    \n
    \n
    \n \n\n\n\n \n
    \n \n \n\n \n
    \n \n
    \n\n\n\n\n\n\n \n \n \n\n\n \n\n\n\n \nBuy now with 1-click\n\n
    \n \n
    \n\n\n \n \n Add to wish list\n\n\n \n \n \n Add to comparison list\n\n\n\n\n\n
    \n\n\n \n
    \n \n
    \n\n\n \n \n\n\n \n\n \n
    \n \n \n
    \n
    \n\n\n\n\n\n\n
    \n\n
    \n \n \n
    \n\n
    \n \n
    \n
    \n \n \n \n \n \n
    \n
    \n
    \n\n\n
    \n \n \n
    \n\n\n\n \n
    \n \n
    \n \n \n
    \n \"\"\n \n
    \n
    \n
    Type the characters you see in the picture above.
    \n
    \n\n\n
    \n\n
    \n \n \n \n\n\n
    \n\n
    \n
    \n\n\n
    \n\n \n \n \n\n\n \n\n\n
    \n \n
    \n\n
    \n \n \n \n
    \n \n

    \r\n\t The T10 camcorder was designed to capture memories in comfort and in style. It boasts an ultra compact size, alightweight body and a brushed metal finish creating a subtle but sophisticated look and feel. In fact, its smooth curves fit so comfortably in your hand, it makes shooting video for longer periods of time more enjoyable\r\n

    \n\n \n
    \n \n \n \n
    \n \n\n\n \n
    \n \n \n \n
    \n \n\n \n
    \n \n \n \n
    \n \n \n\n \n
    \n \n \n \n
    \n \n\n \n
    \n \n \n \n
    \n \n
    \n \n \n
    \n \n
    \n\n \n \n\n \n
    \n \n
    \n\n
    I was looking for a handy and easy-to-use camcorder when I came across this little bird, and I have to say — it really does everything perfectly! Whether you just want to catch some memory in a form of a video, or plan to do a full video project — this camcorder will become your best friend! All the necessary features are present and easily adjustable. I didn't come across any problem using this amazing piece of technology. Definitely worth its money!
    \n \n \n \n
    \n \n \n
    \n \n \n \n \n \n \n \n \n \n \n \n\n
    \n \n\n
    \n \n\n \n\n\n
    \n \n
    \n\n
    \n \n \n\n Write a review\n\n
    \n \n
    \n\n \n
    \n \n \n \n
    \n \n\n \n
    \n \n
    \n\n\n\n \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n\n\n\n\n \n \n\n \n\n
    \n\n \n\n
    \n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\tHave a question?\n\t\"\"\n\t\n\n
    \n\t
    \n\n \n \n \n\n\t\t\n\t\t\t\n\t\t\n\t\t
    \n\t\t\t

    Have a question about CS-Cart?

    \n\t\t\t

    Don't waste your time, just ask now. It's free.

    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t\t\n\t\t\t
    \n\t\t\t\n\t\t
    \n\t\t
    \n\t\t\t
    \n\t\t\t\tAlex\n\t\t\t\tHead of Sales Department\n\t\t\t
    \n\t\t\t\"\"\n\t\t
    \n\t
    \n
    \n
    \n\t\n\t\t\n\t\n\t
    \n\t\t

    Thank you for your interest in CS-Cart!

    \n\t\tIf today is not a day off or a holiday, we'll do our best to answer your questions in the next few hours.\n\t\tClose the pop-up\n\t
    \n
    \n\n\n\n", "page_id": "b0ab3b6e97e542f641fbe9862f9302a3faa4e96c", "page_type": "item", "plugins": { "annotations-plugin": { "extracts": [ { "accept_selectors": [ ".ty-product-block > .ty-product-block__wrapper > .ty-product-block__left > .cm-disable-empty-files > .prices-container > .ty-product-prices > .ty-product-block__price-actual > .cm-reload-172 > .ty-price > span:nth-child(2)" ], "container_id": "b99f-4e2d-8397", "data": { "435b-4450-a595": { "attribute": "content", "extractors": {}, "field": "7cd5-4420-80fd", "required": true } }, "id": "35bc-41f5-8f4a", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": ".content-grid > div:nth-child(2) > .span16 > .ty-product-block > .ty-product-block__wrapper > .ty-product-block__left > .cm-disable-empty-files > .prices-container > .ty-product-prices > .ty-product-block__price-actual > .cm-reload-172 > .ty-price > span:nth-child(2)", "tagid": null }, { "accept_selectors": [ ".content-grid > div:nth-child(2) > .span16 > .ty-product-block > .cm-tabs-content > .content-description > div > p" ], "container_id": "b99f-4e2d-8397", "data": { "a9a1-4d3b-bb42": { "attribute": "content", "extractors": {}, "field": "f9e8-477c-b62d", "required": true } }, "id": "3ccb-43a4-ae26", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": ".content-grid > div:nth-child(2) > .span16 > .ty-product-block > .cm-tabs-content > .content-description > div > p", "tagid": null }, { "accept_selectors": [ ".content-grid > div:nth-child(2) > .span16 > .ty-product-block > .ty-product-block__wrapper > .ty-product-block__left > .cm-disable-empty-files > .ty-product-block__sku > .ty-control-group > .ty-control-group__item" ], "container_id": "b99f-4e2d-8397", "data": { "da9d-4e12-99b4": { "attribute": "content", "extractors": {}, "field": "7e1a-423a-8d72", "required": true } }, "id": "d729-4b88-a203", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": ".content-grid > div:nth-child(2) > .span16 > .ty-product-block > .ty-product-block__wrapper > .ty-product-block__left > .cm-disable-empty-files > .ty-product-block__sku > .ty-control-group > .ty-control-group__item", "tagid": null }, { "accept_selectors": [ ".ty-product-block-title" ], "container_id": "b99f-4e2d-8397", "data": { "e783-4ecd-bd63": { "attribute": "content", "extractors": {}, "field": "2a4e-4258-bf75", "required": false } }, "id": "ab16-4188-b82d", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": ".content-grid > div:nth-child(2) > .span16 > .ty-product-block > .ty-product-block__wrapper > .ty-product-block__left > .cm-disable-empty-files > .ty-product-block-title", "tagid": null }, { "accept_selectors": [ ".ty-breadcrumbs__a:nth-child(2n+3)" ], "container_id": "b99f-4e2d-8397", "data": { "4924-450b-a057": { "attribute": "content", "extractors": {}, "field": "20da-452f-a246", "required": true } }, "id": "2827-40c5-bef4", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "css", "selector": ".ty-breadcrumbs__a:nth-child(2n+3)", "tagid": null }, { "container_id": "b99f-4e2d-8397", "data": { "4924-450b-a057": { "attribute": "content", "extractors": {}, "field": "20da-452f-a241", "required": true } }, "id": "2827-40c5-bef5", "selection_mode": "xpath", "selector": "#in_stock_info_172", "xpath": ".product_page > .row > div:nth-child(1) > .carousel > .thumbnail > .carousel-inner > .item > img", "tagid": null }, { "accept_selectors": [ ".ty-product-img a:first-child img" ], "container_id": "b99f-4e2d-8397", "data": { "9a25-4104-ad86": { "attribute": "src", "extractors": {}, "field": "19f1-4e56-a3de", "required": true } }, "id": "22e7-4c49-ad0c", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "css", "selector": ".ty-product-img a img", "tagid": null }, { "accept_selectors": [ "#notinpage" ], "container_id": "b99f-4e2d-8397", "data": { "9a25-4104-ad86": { "attribute": "src", "extractors": {}, "field": "19f1-4e56-a3de", "required": true } }, "id": "22e7-4c49-ad0d", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": "#notinpage", "tagid": null }, { "accept_selectors": [ ".content-grid" ], "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "b99f-4e2d-8397", "item_container": true, "reject_selectors": [], "repeated": false, "required": [], "schema_id": "3133-422d-be9d", "selector": ".content-grid", "siblings": 0, "tagid": 39, "text-content": "#portia-content" } ] } }, "scrapes": "3133-422d-be9d", "spider": "demo.cs-cart.com", "url": "http://demo.cs-cart.com/electronics/cameras-and-photo/camcorders/compact-full-hd-camcorder/", "version": "0.13.0b20", "schemas": { "3133-422d-be9d": { "fields": { "19f1-4e56-a3de": { "id": "19f1-4e56-a3de", "name": "images", "required": false, "type": "text", "vary": false }, "20da-452f-a246": { "id": "20da-452f-a246", "name": "categories", "required": false, "type": "text", "vary": false }, "2a4e-4258-bf75": { "id": "2a4e-4258-bf75", "name": "name", "required": false, "type": "text", "vary": false }, "7cd5-4420-80fd": { "id": "7cd5-4420-80fd", "name": "price", "required": false, "type": "text", "vary": false }, "7e1a-423a-8d72": { "id": "7e1a-423a-8d72", "name": "sku", "required": false, "type": "text", "vary": false }, "8cce-4538-a736": { "name": "field7", "required": false, "type": "text", "vary": false }, "f9e8-477c-b62d": { "id": "f9e8-477c-b62d", "name": "description", "required": false, "type": "text", "vary": false } }, "name": "product" } }, "results": [ { "_template": "b0ab3b6e97e542f641fbe9862f9302a3faa4e96c", "_type": "product", "20da-452f-a241": [ "In stock" ], "categories": [ "Electronics", "Cameras & Photo", "Camcorders" ], "description": [ "The T10 camcorder was designed to capture memories in comfort and in style. It boasts an ultra compact size, alightweight body and a brushed metal finish creating a subtle but sophisticated look and feel. In fact, its smooth curves fit so comfortably in your hand, it makes shooting video for longer periods of time more enjoyable" ], "images": [ "http://demo.cs-cart.com/images/thumbnails/280/176/detailed/0/T10_use_5.jpg", "http://demo.cs-cart.com/images/thumbnails/280/280/detailed/0/T10_F2_O_1024x768.jpg", "http://demo.cs-cart.com/images/thumbnails/280/280/detailed/0/T10_S1_O_1024x768.jpg", "http://demo.cs-cart.com/images/thumbnails/280/280/detailed/0/T10_F2_O_1024x768_dimg_2.jpg", "http://demo.cs-cart.com/images/thumbnails/280/280/detailed/0/T10_FS3_O_1024x768.jpg", "http://demo.cs-cart.com/images/thumbnails/280/280/detailed/0/T10_T_O_1024x768_2.jpg", "http://demo.cs-cart.com/images/thumbnails/280/190/detailed/0/T10_FS5_O_1024x768_2.jpg" ], "name": [ "Compact Full HD Camcorder" ], "price": [ "299.99" ], "sku": [ "Y0172YCAWT" ], "url": "http://url" } ] } ================================================ FILE: slybot/slybot/tests/data/templates/daft_ie.html ================================================ Houses for Sale in Ireland | Daft.ie

    Advanced Search
    Sort by: Found 24,261 properties. Displaying properties 1 - 10 below

    Houses for sale in Ireland

    1. 17 Portland Drive, Newcastle West, Co. Limerick - Detached House

    BER D1

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €139,000
    • Detached House|
    • 3 Beds|
    • 1 Bath

    Representing excellent value at the asking price, this 3 bedroom dormer style residence is located within walking distance to all local ameanities. Accommodation comprises:...

    2. Templeathea, Athea, Co. Limerick - Detached House

    BER C2

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €224,000
    • Detached House|
    • 4 Beds|
    • 3 Baths

    This superb residence is built to the highest standards and offers circa 2,300 sq ft of beautifully finished living space. Ground floor accommodation comprises entrance hall...

    3. Rath, Abbeyshrule, Co. Longford - Detached House

    BER G

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €120,000
    • Detached House|
    • 2 Beds|
    • 1 Bath

    A charming and unique property. Detached cottage on circa 1/2 acre. Accommodation includes 2 bedrooms, kitchen, livingroom and bathroom. Lovely features such as timb...

    4. 16 Laverna Dale, Castleknock, Dublin 15 - Semi-Detached House

    BER D2

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €395,000
    • Semi-Detached House|
    • 4 Beds|
    • 2 Baths

    Lisney (Drumcondra) Well presented and enjoying a private cul de sac setting no. 16 Laverna Dale is a superb four bedroomed family home in a most sought after location. This property offers function...

    5. 6 Mount Eustace Rise, Tyrrelstown, Dublin 15 - Semi-Detached House

    BER D1

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €199,950
    • Semi-Detached House|
    • 3 Beds|
    • 3 Baths

    Wilson Moore Estate and Letting Agents SUPERB 3 BED / 3 BATH HOME A MUST SEE!!! EXCELLENT LOCATION, ATTRACTIVE REAR GARDEN, PARKING, CLOSE TO A HOST OF LOCAL AMENITIES Wilson Moore are proud to introduce you to t...

    6. 107 Upper Kilmacud Road, Stillorgan, Co. Dublin - Semi-Detached House

    BER E2

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €575,000
    • Semi-Detached House|
    • 5 Beds|
    • 4 Baths

    Youngs Estate Agents Prime Stillorgan location and ready to walk in! Super family home, extended ensuring all the extra rooms required are already in situ! 107 has a large, sunny rear garden and off...

    7. 18 Anglers Rest, Beaver row, Donnybrook, Dublin 4 - Townhouse

    BER E1

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €340,000
    • Townhouse|
    • 2 Beds|
    • 2 Baths

    Youngs Estate Agents Great layout in Donnybrook! It's not too often that a two bed-roomed town house comes up in Donnybrook. With easy access to UCD, the city centre, Donnybrook, Ballsbridge and R...

    8. 247 Rossuille, Oldtown, Letterkenny, Co. Donegal - Semi-Detached House

    BER E2

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €110,000
    • Semi-Detached House|
    • 3 Beds|
    • 1 Bath

    Three-bedroom semi-detached family home with large rear garden located within walking distance of Letterkenny Town centre MEASUREMENTS & DETAILS Entrance Hall (2...

    9. Carricknamart, Manorcunningham, Co. Donegal - Detached House

    BER C2

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €225,000
    • Detached House|
    • 4 Beds|
    • 1 Bath

    An impressive four-bedroom family home maintained to high standards throughout offering excellent living accommodation on a large well manicured site. Located less than 9km...

    10. 11 Castle Crescent, Ashbourne, Co. Meath - Semi-Detached House

    BER C3

    What is BER?

    A Building Energy Rating (BER) indicates the energy performance of a property. Using a scale of A to G, higher rated homes will have lower energy bills.

    Learn more
    €270,000
    • Semi-Detached House|
    • 4 Beds|
    • 1 Bath

    Sherry FitzGerald Geraghty Welcome to your new home - 11 Castle Crescent Ashbourne, a beautifully presented, modern and spacious 4 bedroom semi detached home with large open plan kitchen / dining room, integrated garage and private low maintenance rear garden. Sherry FitzGerald Geraghty are delighted to present this lovely 4 bed to the market which boasts...

    ================================================ FILE: slybot/slybot/tests/data/templates/daft_list.json ================================================ {"extractors": {}, "version": "0.13.0", "page_type": "item", "plugins": {"annotations-plugin": {"extracts": [{"text-content": "#portia-content", "selector": "#sr_content", "item_container": true, "annotations": {"#portia-content": "#dummy"}, "id": "repeated#parent"}, {"item_container": true, "container_id": "repeated#parent", "selector": "#sr_content .box", "repeated": true, "id": "repeated", "text-content": "#portia-content", "annotations": {"#portia-content": "#dummy"}}, {"selector": ".box h2", "container_id": "repeated", "data": {"1": {"attribute": "content", "required": true, "field": "address", "extractors": []}}, "annotations": {"content": [{"attribute": "content", "required": true, "field": "address", "extractors": []}]}, "id": "1"}, {"selector": ".ber-hover img", "container_id": "repeated", "data": {"1": {"attribute": "alt", "required": true, "field": "ber", "extractors": []}}, "annotations": {"alt": [{"attribute": "alt", "required": true, "field": "ber", "extractors": []}]}, "id": "2"}, {"selector": ".text-block p", "container_id": "repeated", "data": {"1": {"attribute": "content", "required": false, "field": "description", "extractors": []}}, "annotations": {"content": [{"attribute": "content", "required": false, "field": "description", "extractors": []}]}, "id": "3"}, {"selector": "span.price-change-down", "container_id": "repeated", "data": {"1": {"attribute": "content", "required": true, "field": "price_change", "extractors": []}}, "annotations": {"content": [{"attribute": "content", "required": false, "field": "price_change", "extractors": []}]}, "id": "4"}]}}, "url": "http://www.daft.ie/ireland/houses-for-sale/", "original_body": "\n\n \n Houses for Sale in Ireland | Daft.ie\n \n \n \n\n\n \n \n \n \n\n \n\n\n \n\n\n\n\n\n\n
    \n
    \n \n Home\n \n /\n \n Search Residential Property for Sale\n \n \n \n /\n \n Ireland Houses for Sale\n \n \n \n \n 178,394 properties online\n \n (746 in the last 24 hours)\n \n \n
    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    Save this search
    \n
    \n \"Draft\n \n \n
    \n \n \n \n \n \"saving\n \n Cancel\n \n \n \n \n
    \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Sign up

    \n\n \n

    \n \n\n \n

    \n \n\n \n

    \n \n\n \n

    \n \n\n \n

    \n \n\n \n

    \n \n\n
    \n

    \n By submitting you agree to Daft's\n Terms of Use and\n Privacy Policy\n

    \n
    \n \"loading\n Sign up\n\n
    \n\n
    \n \n \n\n \n \n
    \n\n
    \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    Create an email alert for this search.
    \n
    \n \"Draft\n \n \n
    \n \n \n \n
    \n \n \n
    \n \n \"saving\n Cancel\n \n
    \n \n
    \n
    \n
    \n
    \n \n\n
    \n
    \n\n
    \n
    \n
    \n \n
    \n \n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n \n
    \n Advanced\n Search\n \n\n\n
    \n
    \n
    \n \n Sort by:\n Found 20,568 properties.\n \n Displaying properties 1 - 10 below
    \n

    \n Houses for sale in Ireland

    \n
    \n
    \n
    \n
    \n
    \n\n \n \n \n \n \n
    \n \n
    \n
    \n
    \n\n
    \n

    \n 1. \n \n 5 Friary Court, Park Road, Killarney, Co. Kerry - Terraced House \n \n

    \n \n \n \n \"BER\n \n \n
    \n \n \n

    What is BER?

    \n

    \n A Building Energy Rating (BER) indicates the energy performance of\n a property. Using a scale of A to G, higher rated homes will\n have lower energy bills.\n

    \n Learn more\n
    \n
    \n
    \n \n\n
    \n\n
    \n €145,000\n
      \n
    • \n Terraced House|
    • \n
    • \n 2 Beds|
    • \n
    • \n 1 Bath
    • \n
    \n
    \n\n

    \n \n Conveniently located townhouse in courtyard development, just off the Park Road.\nThe town house which is in walk in condition comprises on the ground floor open plan kitchen d...

    \n\n\n\n
    \n
    Upcoming viewings:
    \n
    \n \n
    \n
    \n Mar\n
    \n
    \n 15\n
    \n
    \n
    \n
    \n Tue, Mar 15th, 5:00 - 5:30pm\n
    \n
    \n
    \n
    \n
    \n\n
    \n

    \n 2. \n \n 16 Deerpark Avenue, Castleknock, Dublin 15 - Detached House \n \n

    \n \n \n \n \"BER\n \n \n
    \n \n \n

    What is BER?

    \n

    \n A Building Energy Rating (BER) indicates the energy performance of\n a property. Using a scale of A to G, higher rated homes will\n have lower energy bills.\n

    \n Learn more\n
    \n
    \n
    \n \n\n
    \n\n
    \n €1,300,000\n
      \n
    • \n Detached House|
    • \n
    • \n 4 Beds|
    • \n
    • \n 3 Baths
    • \n
    \n
    \n\n

    \n \n \"Sherry\n \n \n Sherry FitzGerald are privilidged to present for sale this exceptional detached family home. Beautifully presented and maintained, it boasts a spectacular, south facing, landscaped, mature rear garden which extends to an impressive 110ft approx. in length. This garden is teeming with mature trees and and well chosen specimen...

    \n\n\n
    \n \n View more details & 12 more photos\n \n Call: Michelle Curran at\n 8201800\n \n
    \n
    \n
    Upcoming viewings:
    \n
    \n \n
    \n
    \n Mar\n
    \n
    \n 12\n
    \n
    \n
    \n
    \n Sat, Mar 12th, 1:15 - 1:45pm\n
    \n
    \n
    \n
    \n
    \n\n
    \n

    \n 3. \n \n Ard Aulinn, Mungret, Co. Limerick - Detached House \n \n

    \n \n \n \n \"BER\n \n \n
    \n \n \n

    What is BER?

    \n

    \n A Building Energy Rating (BER) indicates the energy performance of\n a property. Using a scale of A to G, higher rated homes will\n have lower energy bills.\n

    \n Learn more\n
    \n
    \n
    \n \n\n
    \n\n
    \n €330,000\n
      \n
    • \n Detached House|
    • \n
    • \n 4 Beds|
    • \n
    • \n 4 Baths
    • \n
    \n
    \n\n

    \n \n \"GL\n \n \n Accommodation: \n\nLarge entrance hall, tiled flooring. Guest toilet & Whb. \nVery spacious open plan fitted kitchen cum dining area, tiled flooring & slash back, french doors leading to private enclosed rear garden.\nLarge utilty room which is plumbed & fitted. \nDouble doors leading large living room with feature fireplac...

    \n\n\n
    \n \n View more details & 8 more photos\n \n Call: Geraldine Leddin at\n 086-265 1380\n \n
    \n
    \n
    \n
    \n\n
    \n

    \n 4. \n \n Bay View House, Fieldstown, Monasterboice, Co. Louth - Detached House \n \n

    \n \n \n \n \"BER\n \n \n
    \n \n \n

    What is BER?

    \n

    \n A Building Energy Rating (BER) indicates the energy performance of\n a property. Using a scale of A to G, higher rated homes will\n have lower energy bills.\n

    \n Learn more\n
    \n
    \n
    \n \n\n
    \n\n
    \n €289,000\n
    \n \n €10,000\n \n
    \n
      \n
    • \n Detached House|
    • \n
    • \n 3 Beds|
    • \n
    • \n 2 Baths
    • \n
    \n
    \n\n

    \n \n \"Sullivan\n \n \n We are pleased to offer to the market this three bedroom red brick bungalow in Fieldstown, Monasterboice which is a ten minute drive from Drogheda town and the M1 Motorway. The pr...

    \n\n\n\n
    \n
    \n
    \n\n
    \n

    \n 5. \n \n Tatestown, Donaghpatrick, Navan, Co. Meath - Detached House \n \n

    \n \n \n \n \"BER\n \n \n
    \n \n \n

    What is BER?

    \n

    \n A Building Energy Rating (BER) indicates the energy performance of\n a property. Using a scale of A to G, higher rated homes will\n have lower energy bills.\n

    \n Learn more\n
    \n
    \n
    \n \n\n
    \n\n
    \n €330,000\n
      \n
    • \n Detached House|
    • \n
    • \n 4 Beds|
    • \n
    • \n 2 Baths
    • \n
    \n
    \n\n

    \n \n \"Sherry\n \n \n Well presented bungalow set on a generous site of circa. 0.667 of an acre only 4.5km from Navan Town. The property has been well maintained by the present owners and benefits from bright and airy rooms. Accommodation. Kitchen, dining room, living room, utility, 4 bedrooms (master en-suite), bathroom.

    \n\n\n
    \n \n View more details & 14 more photos\n \n Call: Ed Reilly at\n 0469060450\n \n
    \n
    \n
    \n\n
    \n\n
    \n

    \n 6. \n \n Carrig East, Clarina, Co. Limerick - Detached House \n \n

    \n \n \n \n \"BER\n \n \n
    \n \n \n

    What is BER?

    \n

    \n A Building Energy Rating (BER) indicates the energy performance of\n a property. Using a scale of A to G, higher rated homes will\n have lower energy bills.\n

    \n Learn more\n
    \n
    \n
    \n \n\n
    \n\n
    \n €289,000\n
      \n
    • \n Detached House|
    • \n
    • \n 6 Beds|
    • \n
    • \n 2 Baths
    • \n
    \n
    \n\n

    \n \n \"M&C\n \n \n Carrig East represents one of the most interesting and versatile properties of its kind to be brought to the market in recent years. This substantial family home has been well ma...

    \n\n\n\n
    \n
    \n
    \n\n
    \n

    \n 7. \n \n 29 Anchor Mews, Arklow, Co. Wicklow - Terraced House \n \n

    \n \n \n \n \"BER\n \n \n
    \n \n \n

    What is BER?

    \n

    \n A Building Energy Rating (BER) indicates the energy performance of\n a property. Using a scale of A to G, higher rated homes will\n have lower energy bills.\n

    \n Learn more\n
    \n
    \n
    \n \n\n
    \n\n
    \n €125,000\n
      \n
    • \n Terraced House|
    • \n
    • \n 2 Beds|
    • \n
    • \n 1 Bath
    • \n
    \n
    \n\n

    \n \n \"CD\n \n \n This apartment on the 1st floor was built in 1998. A small development overlooking the river & South Quay Harbour & only a few minutes walk from the beach. Electric gates front the ...

    \n\n\n\n
    \n
    \n
    \n\n \n \n\n
    \n\n
    \n €135,000\n
      \n
    • \n Detached House|
    • \n
    • \n 4 Beds|
    • \n
    • \n 2 Baths
    • \n
    \n
    \n\n

    \n \n \"ALLIANCE\n \n \n Peter Quinn Auctioneer is delighted to bring this lovely 4 bedroom detached dormer bungalow to the market in walk in condition.\nThis property is situated on the outskirts of C...

    \n\n\n\n
    \n
    \n
    \n\n \n \n\n
    \n\n
    \n €265,000\n
      \n
    • \n Semi-Detached House|
    • \n
    • \n 3 Beds|
    • \n
    • \n 3 Baths
    • \n
    \n
    \n\n

    \n \n \"CD\n \n \n Accommodation\n\nEntrance Hallway 4.6m x 2m with polished tiled floor\n\nLiving Room 4.2m x 3.6m with Bay window, and views over Wicklow bay\n and the Irish Sea, gran...

    \n\n\n\n
    \n
    \n
    \n\n
    \n

    \n 10. \n \n 65 Fan Glas, Kilmeadan, Co. Waterford - Terraced House \n \n

    \n \n \n \n \"BER\n \n \n
    \n \n \n

    What is BER?

    \n

    \n A Building Energy Rating (BER) indicates the energy performance of\n a property. Using a scale of A to G, higher rated homes will\n have lower energy bills.\n

    \n Learn more\n
    \n
    \n
    \n \n\n
    \n\n
    \n €165,000\n
      \n
    • \n Terraced House|
    • \n
    • \n 3 Beds|
    • \n
    • \n 3 Baths
    • \n
    \n
    \n\n

    \n \n \"Guiry\n \n \n Newly built 3 bedroom mid terrace. Ready for immediate occupancy NO 65 Fan Glas would make an ideal start home. Situated in the Village of Kilmeadan Fan Glas is close to the new bi-...

    \n\n\n\n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n © Daft Media Limited 1997 - 2016\n \n
    \n
    \n Sites:\n \n
    \n
    \n
    \n\n \n \n", "scrapes": "default", "id": "1", "name": "house_list"} ================================================ FILE: slybot/slybot/tests/data/templates/firmen.wko.at.html ================================================ Elektrotechnik - Firmen A-Z
    arrow-up arrow-right arrow-left arrow-down close help popup phone mobile fax email web editieren location search th location-1 location-2 2 location-3 3 location-4 4 location-5 5 location-6 6 location-7 7 location-8 8 location-9 9 location-10 10

    Ihre Suchabfrage Elektrotechnik liefert mehr als 1000 Treffer

    Filtern nach:

    Treffer ohne Kontaktdaten:

    Karte

    Sortieren nach:

    ================================================ FILE: slybot/slybot/tests/data/templates/firmen.wko.at.json ================================================ { "extractors": {}, "id": "2688-4a8e-8b29", "name": "Elektrotechnik - Firmen A-Z", "page_id": "", "page_type": "item", "plugins": { "annotations-plugin": { "extracts": [ { "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "75f8-4fdc-b4e3#parent", "item_container": true, "repeated": false, "required": [], "schema_id": "020e-42fe-8006", "selector": "#result > .container", "siblings": 0, "tagid": null, "text-content": "#portia-content" }, { "annotations": { "#portia-content": "#dummy" }, "container_id": "75f8-4fdc-b4e3#parent", "id": "75f8-4fdc-b4e3", "item_container": true, "repeated": true, "required": [], "schema_id": "020e-42fe-8006", "selector": ".col1-right", "siblings": 0, "tagid": null, "text-content": "#portia-content" }, { "accept_selectors": [ "[itemprop= \"name\"]" ], "container_id": "75f8-4fdc-b4e3", "data": { "e04a-4184-91a1": { "attribute": "content", "extractors": {}, "field": "5adf-43c6-8113", "required": false } }, "id": "24dd-4492-95a6", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": true, "required": [], "selection_mode": "css", "selector": "[itemprop= \"name\"]", "tagid": null, "text-content": "content", "xpath": "//" }, { "accept_selectors": [ "[itemprop=\"streetAddress\"]" ], "container_id": "75f8-4fdc-b4e3", "data": { "cd41-429d-a779": { "attribute": "content", "extractors": {}, "field": "0247-457c-8591", "required": false } }, "id": "80f0-4a7f-a632", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": true, "required": [], "selection_mode": "css", "selector": "[itemprop=\"streetAddress\"]", "tagid": null, "text-content": "content", "xpath": "//" }, { "accept_selectors": [ "[itemprop=\"addressLocality\"]" ], "container_id": "75f8-4fdc-b4e3", "data": { "4b2e-4235-9bb3": { "attribute": "content", "extractors": {}, "field": "b9eb-4347-b68e", "required": false } }, "id": "0523-45f0-b261", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": true, "required": [], "selection_mode": "css", "selector": "[itemprop=\"addressLocality\"]", "tagid": null, "text-content": "content", "xpath": "//" }, { "accept_selectors": [ "div [class = \"authorization\"]" ], "container_id": "75f8-4fdc-b4e3", "data": { "c230-47ae-abfd": { "attribute": "content", "extractors": {}, "field": "ae31-4c8e-b4e9", "required": false } }, "id": "4cd3-42fd-b9ad", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": true, "required": [], "selection_mode": "css", "selector": "div [class = \"authorization\"]", "tagid": null, "text-content": "content", "xpath": "//" }, { "accept_selectors": [ "article:nth-child(1) > .row > .col-md-12 > .row > .col1 > .col1-right > .zip", "article:nth-child(2) > .row > .col-md-12 > .row > .col1 > .col1-right > .zip" ], "container_id": "75f8-4fdc-b4e3", "data": { "5a8e-420e-ac4a": { "attribute": "content", "extractors": {}, "field": "d07b-407d-9306", "required": false } }, "id": "7515-40d7-b291", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": false, "required": [], "selection_mode": "auto", "selector": ".col1-right > .zip", "tagid": null, "text-content": "content", "xpath": "//*[contains(concat(\" \", @class, \" \"), \" col1-right \")]/*[contains(concat(\" \", @class, \" \"), \" zip \")]" }, { "accept_selectors": [ "[itemprop=\"email\"]" ], "container_id": "75f8-4fdc-b4e3", "data": { "5af1-424e-bc2b": { "attribute": "content", "extractors": {}, "field": "3a2a-459d-9468", "required": false } }, "id": "b23c-4d06-8b73", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": false, "required": [], "selection_mode": "css", "selector": "[itemprop=\"email\"]", "tagid": null, "text-content": "content", "xpath": "//" }, { "accept_selectors": [ "[itemprop=\"url\"]" ], "container_id": "75f8-4fdc-b4e3", "data": { "9504-477d-b1c7": { "attribute": "href", "extractors": {}, "field": "27f0-400d-98a7", "required": false } }, "id": "7884-4ce8-93f4", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": false, "required": [], "selection_mode": "css", "selector": "[itemprop=\"url\"]", "tagid": null, "text-content": "content", "xpath": "//" }, { "accept_selectors": [ "div[class=\"icon-mobile vcard__info\"] > a" ], "container_id": "75f8-4fdc-b4e3", "data": { "88ce-4d5e-8c08": { "attribute": "content", "extractors": {}, "field": "db09-4a64-9f64", "required": false } }, "id": "be35-47ad-987d", "post_text": null, "pre_text": null, "reject_selectors": [], "repeated": false, "required": [], "selection_mode": "css", "selector": "div[class=\"icon-mobile vcard__info\"] > a", "tagid": null, "text-content": "content", "xpath": "///a" } ] } }, "results": [{ "website": [ "http://www.3e-technik.at/" ], "city": [ "Wien" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "3E-Technik e.U." ], "_index": 1, "mobile": [ "+43 699 112 199 14" ], "url": "http://url", "street": [ "Grellgasse 9/3/2" ], "branch": [ "Elektrotechnik" ], "_template": "2688-4a8e-8b29", "email": [ "office@3e-technik.at" ] }, { "website": [ "http://www.elektro-jamnik.at/" ], "city": [ "Seefeld in Tirol" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "A. Jamnik Elektro GmbH" ], "_index": 5, "url": "http://url", "street": [ "M\u00fcnchner Stra\u00dfe 487" ], "branch": [ "Elektrotechnik" ], "_template": "2688-4a8e-8b29", "email": [ "a.jamnik.elektro@aon.at" ] }, { "city": [ "Wien" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "A.A.A. 3 Ampere - Aqua - Art Elektro-, Gas-, Wasser-, Heizungsinstallationsgesellschaft m.b.H." ], "_index": 9, "url": "http://url", "street": [ "Am Tabor 1-3" ], "branch": [ "Elektrotechnik" ], "_template": "2688-4a8e-8b29" }, { "city": [ "Wien" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "A.A.A. 3 Ampere - Aqua - Art Elektro-, Gas-, Wasser-, Heizungsinstallationsgesellschaft m.b.H." ], "_index": 13, "url": "http://url", "street": [ "Kolpingstra\u00dfe 4" ], "branch": [ "Elektrotechnik" ], "_template": "2688-4a8e-8b29" }, { "website": [ "http://www.aaves.at/" ], "city": [ "Ebenthal" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "AAVES Sicherheitstechnik GmbH" ], "_index": 17, "mobile": [ "+43 (0) 664 203 75 95" ], "url": "http://url", "street": [ "Gewerbezone, Zeiss Stra\u00dfe 16" ], "branch": [ "Elektrotechnik" ], "_template": "2688-4a8e-8b29", "email": [ "office@aaves.at" ] }, { "city": [ "Esternberg" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "ABM Tech GmbH" ], "_index": 21, "url": "http://url", "street": [ "Hauptstra\u00dfe 53/1" ], "branch": [ "Elektrotechnik; Errichter von Alarmanlagen" ], "_template": "2688-4a8e-8b29", "email": [ "office@abmtech.at" ] }, { "website": [ "http://www.elektro-acherer.at/" ], "city": [ "Kufstein" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "Harald Acherer - ELEKTRO ACHERER" ], "_index": 25, "url": "http://url", "street": [ "Herzog-Erich-Stra\u00dfe 12" ], "branch": [ "Elektrotechnik" ], "_template": "2688-4a8e-8b29", "email": [ "el.acherer@kufnet.at" ] }, { "website": [ "http://www.aes-energietechnik.at/" ], "city": [ "Ottenschlag" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "AES - Energie Technik GmbH Alternative Energie Systeme" ], "_index": 29, "mobile": [ "0664 885 018 83" ], "url": "http://url", "street": [ "Spitzerstr. 24" ], "branch": [ "Elektrotechnik" ], "_template": "2688-4a8e-8b29", "email": [ "office@aes-energietechnik.at" ] }, { "website": [ "http://www.aes.co.at/" ], "city": [ "Treibach-Althofen" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "AES alternativENERGIEsysteme e.U." ], "_index": 33, "mobile": [ "+43 664 307 47 03" ], "url": "http://url", "street": [ "Hauptplatz 3 - 4" ], "branch": [ "Errichter von Photovoltaikanlagen" ], "_template": "2688-4a8e-8b29", "email": [ "elpo1@gmx.at" ] }, { "website": [ "http://www.agetech.at/" ], "city": [ "Lienz" ], "_type": "Elektrotechnik - Firmen A-Z", "name": [ "AGEtech GmbH - smart electric" ], "_index": 37, "url": "http://url", "street": [ "Beda-Weber-Gasse 10" ], "branch": [ "Elektrotechnik" ], "_template": "2688-4a8e-8b29", "email": [ "info@agetech.at" ] } ], "scrapes": "020e-42fe-8006", "schemas": { "020e-42fe-8006": { "fields": { "5adf-43c6-8113": { "id": "5adf-43c6-8113", "name": "name", "required": true, "type": "text", "vary": false }, "0247-457c-8591": { "id": "0247-457c-8591", "name": "street", "required": false, "type": "text", "vary": false }, "84c7-48fa-b3cb": { "id": "84c7-48fa-b3cb", "name": "plz", "required": false, "type": "text", "vary": false }, "b9eb-4347-b68e": { "id": "b9eb-4347-b68e", "name": "city", "required": false, "type": "text", "vary": false }, "ae31-4c8e-b4e9": { "id": "ae31-4c8e-b4e9", "name": "branch", "required": true, "type": "text", "vary": false }, "8953-460a-b810": { "id": "8953-460a-b810", "name": "landline", "required": false, "type": "text", "vary": false }, "7a4b-4723-a3a1": { "id": "7a4b-4723-a3a1", "name": "phone_2", "required": false, "type": "text", "vary": false }, "db09-4a64-9f64": { "id": "db09-4a64-9f64", "name": "mobile", "required": false, "type": "text", "vary": false }, "e706-4d94-be4f": { "id": "e706-4d94-be4f", "name": "fax", "required": false, "type": "text", "vary": false }, "2e6e-498d-81c3": { "id": "2e6e-498d-81c3", "name": "e-mail", "required": false, "type": "text", "vary": false }, "27f0-400d-98a7": { "id": "27f0-400d-98a7", "name": "website", "required": false, "type": "url", "vary": false }, "d07b-407d-9306": { "auto_created": true, "id": "d07b-407d-9306", "name": "field1", "required": false, "type": "text", "vary": false }, "3a2a-459d-9468": { "id": "3a2a-459d-9468", "name": "email", "required": false, "type": "text", "vary": false } }, "name": "Elektrotechnik - Firmen A-Z" } }, "spider": "firmen.wko.at", "url": "https://firmen.wko.at/Web/Ergebnis.aspx?StandortID=0&Branche=24170&BranchenName=Elektrotechnik&CategoryID=0&Filter=1&Page=3", "version": "0.13.0b37" } ================================================ FILE: slybot/slybot/tests/data/templates/hn.html ================================================ Hacker News
    Hacker Newsnew | comments | show | ask | jobs | submit login
    1.
    Edward Snowden interview: 'Smartphones can be taken over' (bbc.co.uk)
    31 points by mhandley 22 minutes ago | 1 comment
    2.
    Trans-Pacific Partnership Trade Deal Is Reached (nytimes.com)
    272 points by shill 4 hours ago | 231 comments
    3.
    Twitter Names Jack Dorsey Chief Executive (nytimes.com)
    170 points by jvrossb 4 hours ago | 104 comments
    4.
    Immutable Data Structures and JavaScript (jlongster.com)
    81 points by jlongster 3 hours ago | 30 comments
    5.
    CROBOTS is a programming game, for programmers or aspiring programmers (1985) (tpoindex.github.io)
    40 points by tpoindex 2 hours ago | 7 comments
    6.
    CloudFlare Route leak (cloudflarestatus.com)
    14 points by anon1385 39 minutes ago | 15 comments
    7.
    Microsoft, stop sending user identifiers in clear text (annoyedmicrosoftuser.blogspot.com)
    142 points by ramen-hero 6 hours ago | 30 comments
    8.
    One of few places on Earth where an international boundary can be seen at night (nasa.gov)
    74 points by vinnyglennon 1 hour ago | 23 comments
    9.
    How to Write a Pac-Man Game in JavaScript (2004) (masswerk.at)
    43 points by franze 4 hours ago | 8 comments
    10.
    Closing a door (thesharps.us)
    154 points by clessg 2 hours ago | 72 comments
    11.
    Peeple sites 'disappear' from web after backlash over app (bbc.co.uk)
    20 points by Turukawa 47 minutes ago | 10 comments
    12.
    IBM is still making ThinkPad keyboards (mthompson.org)
    5 points by cblop 39 minutes ago | 1 comment
    13.
    KeepassC – Curses based keepass written in Rust (raymontag.github.io)
    75 points by Immortalin 7 hours ago | 35 comments
    14.
    Show HN: YouTransfer – Self-hosted file sharing (youtransfer.io)
    106 points by rbolte 9 hours ago | 60 comments
    15.
    The Nobel Prize in Physiology or Medicine 2015 (nobelprize.org)
    51 points by globuous 6 hours ago | 5 comments
    16.
    Wheels for the Sieve of Eratosthenes (vicarie.in)
    15 points by narendraj9 3 hours ago | 2 comments
    17.
    A cartoon guide to Flux (medium.com)
    162 points by snehesht 13 hours ago | 26 comments
    18.
    Unsupervised Feature Learning and Deep Learning Tutorial (stanford.edu)
    154 points by Katydid 11 hours ago | 15 comments
    19.
    Heroku2scalingo: migrate from Heroku to Scalingo in a minute (scalingo.com)
    84 points by _Soulou 7 hours ago | 31 comments
    20.
    Satellite Internet gets a fresh look, cash infusion (ctvnews.ca)
    34 points by evilsimon 9 hours ago | 28 comments
    21.
    Reverse Engineering Proves Journalist Security App Is Not Secure (vice.com)
    59 points by secfirstmd 10 hours ago | 8 comments
    22. Roost (YC S14) is hiring a senior dev in NYC to help build the future of the web
    2 hours ago
    23.
    Annotated version of Bell's inequalities, Quantum Mechanics' ultimate test (fermatslibrary.com)
    31 points by thegreatpele 8 hours ago | discuss
    24.
    Why Cats Were Hated in Medieval Europe (medievalists.net)
    70 points by diodorus 13 hours ago | 52 comments
    25.
    Origin of the name “Google” (stanford.edu)
    53 points by crivabene 8 hours ago | 23 comments
    26.
    Mecca Then and Now – 128 Years of Growth (theatlantic.com)
    110 points by vinnyglennon 4 hours ago | 62 comments
    27.
    Show HN: Goxel, an open-source 3D voxel editor (github.com)
    46 points by guillaumec 12 hours ago | 7 comments
    28.
    Show HN: Someone.io – Task management for teams made easy (someone.io)
    136 points by terjeto 9 hours ago | 66 comments
    29.
    Valeant’s Drug Price Strategy Enriches It, but Infuriates Patients and Lawmakers (nytimes.com)
    38 points by pbhowmic 12 hours ago | 38 comments
    30.
    A Single Neuron May Cary Up to 1000 Genetic Mutations (neurosciencenews.com)
    56 points by ghosh 11 hours ago | 17 comments
    More

    Applications are open for YC Winter 2016

    Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

    Search:
    ================================================ FILE: slybot/slybot/tests/data/templates/patchofland.html ================================================ Crowdfunded Real Estate Investments

    Invest

    Sort
    - Created Date - Loan Term - Loan Amount - Loan Opportunity Type - Investment Status - ARV
    Filter
    - Property Type
    1. Single Family Residential
    2. Multi-Family Residential
    3. Commercial
    - Funding Needed
    $ - $
    - Loan Opportunity Type
    1. 3 - 6 month Transactional
    2. 3 month or less Transactional
    3. Over 6 month Transactional
    4. Purchase & Rehab
    5. Purchase Only
    6. Refinance & Rehab
    7. Refinance Only
    8. Rehab Only
    - Investment Status
    1. Fully Funded
    2. Funding
    - Loan Term
    -
    - Loan Amount
    -
    - ARV
    -
    View
    Grid List

    Are you a Real Estate Developer? Access quality capital fast and list your project here! More info...

    CHIP LLC

    High-End Chicago Remodel

    3719 N Oakley Ave, Chicago, Illinois

    • 12% APR with expected 14 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 3719 N Oakley Ave: 2,971 sq ft / 7 Room / 4 Bedroom / 3 Bath Single Family Residential
    • 72.42% ARV
    • $974,000 Investment offering
    • 12 % APR
    • 72% ARV

    4-Unit DC Suburb Acquisition

    3555 16th Street NW, Washington, DC

    • 11% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 3555 16th Street NW: 2,970 sq ft / 14 Room / 6 Bedroom / 5 Bath Multi-Family Residential
    • 75.03% ARV
    • $634,000 Investment offering
    • 11 % APR
    • 75% LTV

    Purchase near University of Denver

    2329 S. High Street, Denver, Colorado

    • 11% APR with expected 18 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 2329 S. High Street: 1,395 sq ft / 5 Room / 2 Bedroom / 1 Bath Single Family Residential
    • 109.13% ARV
    • $436,500 Investment offering
    • 11 % APR
    • 75% LTV

    Noe Valley Fix and Flip - Phase I

    438 29th St, San Francisco, California

    • 11% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 438 29th St: 975 sq ft / 6 Room / 2 Bedroom / 1 Bath Single Family Residential
    • 64.88% ARV
    • $1,890,000 Investment offering
    • 11 % APR
    • 65% ARV

    Denver CO Purchase and Lease

    2770 S Garfield St., Denver, Colorado

    • 11% APR with expected 18 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 2770 S Garfield St.: 1,013 sq ft / 7 Room / 3 Bedroom / 1 Bath Single Family Residential
    • 71.99% ARV
    • $251,250 Investment offering
    • 11 % APR
    • 74% LTV

    Vermont Library Transformation Refinance

    48 West Rd, Manchester, Vermont

    • 12% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 48 West Rd: 7,877 sq ft / 14 Room / 9 Bedroom / 5 Bath Single Family Residential
    • 63.29% ARV
    • $981,000 Investment offering
    • 12 % APR
    • 63% ARV

    Princeton Fix and Flip

    747 Kingston Road, Princeton, New Jersey

    • 11% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 747 Kingston Road: 1,774 sq ft / 8 Room / 4 Bedroom / 2 Bath Single Family Residential
    • 65.1% ARV
    • $944,000 Investment offering
    • 11 % APR
    • 65% ARV

    Oakland Park Fix and Flip

    4441 NE 15th Avenue, Oakland Park, Florida

    • 12% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 4441 NE 15th Avenue: 1,487 sq ft / 6 Room / 3 Bedroom / 2 Bath Single Family Residential
    • 68.04% ARV
    • $264,000 Investment offering
    • 12 % APR
    • 68% ARV

    Oxford Development Refinance

    3333 Ray Road, Oxford, Michigan

    • 12% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 3333 Ray Road: 4,391 sq ft / 14 Room / 5 Bedroom / 4 Bath Single Family Residential
    • 46.67% ARV
    • $252,000 Investment offering
    • 12 % APR
    • 47% ARV
    • 11% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 4313 Howard Ave: 2,300 sq ft / 12 Room / 6 Bedroom / 3 Bath Multi-Family Residential
    • 3325 Belden St: 1,408 sq ft / 7 Room / 3 Bedroom / 2 Bath Multi-Family Residential
    • 69.85% ARV
    • $300,000 Investment offering
    • 11 % APR
    • 70% ARV

    178-180 Wainwright Fix and Flip

    178-180 Wainwright St, Newark, New Jersey

    • 12% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 178-180 Wainwright St: 4,776 sq ft / 22 Room / 9 Bedroom / 4 Bath Multi-Family Residential
    • 69.78% ARV
    • $157,000 Investment offering
    • 12 % APR
    • 70% ARV

    1044 Los Robles Fix and Flip

    1044 Los Robles Blvd, Sacramento, California

    • 11% APR with expected 12 month hold term
    • Underlying loan secured by first position lien on title and personal guaranty of the individual developer
    • 1044 Los Robles Blvd: 2,165 sq ft / 10 Room / 3 Bedroom / 4 Bath Multi-Family Residential
    • 69.76% ARV
    • $143,000 Investment offering
    • 11 % APR
    • 70% ARV
    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    Sort
    - Created Date - Loan Term - Loan Amount - Loan Opportunity Type - Investment Status - ARV
    View
    Grid List
    ================================================ FILE: slybot/slybot/tests/data/templates/so_annotations.json ================================================ { "annos": [ { "container_id": "5b7c-402c-9d4c", "data": { "3310-4b70-85aa": { "attribute": "content", "extractors": {}, "field": "770d-4a6e-b910", "id": "ee47-4ea0-a374|3310-4b70-85aa", "required": false } }, "id": "ee47-4ea0-a374", "selector": ".question-summary > .summary > .started > .started-link" }, { "annotations": { "#portia-content": "#dummy" }, "container_id": "5b7c-402c-9d4c#parent", "id": "5b7c-402c-9d4c", "item_container": true, "repeated": true, "schema_id": "bb14-43b6-9040", "selector": ".question-summary", "siblings": 0, "text-content": "#portia-content" }, { "container_id": "5b7c-402c-9d4c", "data": { "24f1-443b-b7d5": { "attribute": "content", "extractors": {}, "field": "5249-41c5-b481", "id": "58f4-40ba-9b22|24f1-443b-b7d5", "required": false } }, "id": "58f4-40ba-9b22", "selector": ".question-summary > .summary > h3 > .question-hyperlink" }, { "container_id": "5b7c-402c-9d4c", "data": { "9574-4c8e-bfb5": { "attribute": "content", "extractors": {}, "field": "93b0-4236-94b0", "id": "9df6-4251-a94e|9574-4c8e-bfb5", "required": false } }, "id": "9df6-4251-a94e", "repeated": true, "selection_mode": "auto", "selector": "#question-mini-list > div:nth-child(1) > .summary > .tags > .post-tag" }, { "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "5b7c-402c-9d4c#parent", "item_container": true, "schema_id": "bb14-43b6-9040", "selector": "#qlist-wrapper", "siblings": 0, "text-content": "#portia-content" } ], "items": { "bb14-43b6-9040": { "fields": { "5249-41c5-b481": { "name": "title", "required": 0, "type": "text", "vary": 0 }, "770d-4a6e-b910": { "name": "answered", "required": 0, "type": "text", "vary": 0 }, "93b0-4236-94b0": { "name": "tags", "required": 0, "type": "text", "vary": 0 } }, "name": "question" } }, "results": [ { "_index": 1, "_template": "507f520c3bf361f4c5cd55c44307a271bccb2218", "_type": "question", "answered": [ "asked 51 secs ago" ], "tags": [ "jquery", "twitter-bootstrap", "navbar", "sticky" ], "title": [ "Bootstrap navbar doesn't open - mobile view" ], "url": "http://url" }, { "_index": 53, "_template": "507f520c3bf361f4c5cd55c44307a271bccb2218", "_type": "question", "answered": [ "modified 9 mins ago" ], "tags": [ "javascript" ], "title": [ "Export to Excel issue in Chrome and Firefox" ], "url": "http://url" }, { "_index": 96, "_template": "507f520c3bf361f4c5cd55c44307a271bccb2218", "_type": "question", "answered": [ "asked 1 hour ago" ], "tags": [ "python", "cassandra", "apache-spark", "ipython-notebook" ], "title": [ "iPython + Spark + Cassandra - Py4JJavaError and How to connect to Cassandra from Spark?" ], "url": "http://url" } ] } ================================================ FILE: slybot/slybot/tests/data/templates/stack_overflow.html ================================================ Stack Overflow
    0
    votes
    0
    answers
    2
    views

    Looking for more? Browse the complete list of questions, or popular tags. Help us answer unanswered questions.

    ================================================ FILE: slybot/slybot/tests/data/templates/stips.co.il.html ================================================ איך ההרגשה זה להיות טבעוני?
    5 תשובות
    בגדול זה ממש הרגשה נפלאה, גם בערכים בגוף הכל מתאזן, הכוונה לחץ דם, כולסטרול, סוכר, היציאות, ויש אומרים אפילו מונע מחלות מסוימות.
    לא זוכר איך זה לא להיות טבעוני אני רק יודע שכיום אני בחיים לא עייף ומפוצץ תמיד באנרגיה
    mak
    Mak, אהבתי את הכנות.

    די להתייפיפות. ("כן, זו הרגשה נפלאה ונהדרת, להיות כל כך מוסרי וצדיק וטהור").
    אנונימי
    אבל היום אני טבעוני ומפוצץ באנרגיה (הרבה הרבה יותר מבעבר)
    mak
    אין לי מושג כי אני בחיים לא אהיה טבעוני ותמיד אדבר רע
    על טבעונות/צימחונות לכל מי שיש לי השפעה עליו.
    אני רק יכול לומר לך שכשעובר יום ולא אכלתי בשר
    אז אני מרגיש ריק ולא רגוע.
    התחברות ל

    ההזדהות נכשלה, נסה שנית!
    אם שכחת את הסיסמה שלך לחץ כאן
    עדיין לא הצטרפת לסטיפס?  הרשמה
    באותו הנושא:
    אולי תאהב גם את:
    ================================================ FILE: slybot/slybot/tests/data/templates/stips.co.il.json ================================================ { "extractors": {}, "id": "3fd3-4288-b3dd", "name": "3fd3-4288-b3dd", "page_id": "", "page_type": "item", "plugins": { "annotations-plugin": { "extracts": [ { "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "bf9e-40b6-959f", "item_container": true, "repeated": false, "required": [], "schema_id": "2cdc-4284-ab08", "selector": "#page-header", "siblings": 0, "tagid": null, "text-content": "#portia-content" }, { "accept_selectors": [ "h1" ], "container_id": "bf9e-40b6-959f", "data": { "021b-4b2d-9526": { "attribute": "content", "extractors": {}, "field": "22a1-4765-82a1", "required": false } }, "id": "daca-42ad-9d73", "text-content": "content", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "repeated": false, "selection_mode": "auto", "selector": "#page-header > .item-title > h1", "tagid": null, "xpath": "//*[@id=\"page-header\"]/*[contains(concat(\" \", @class, \" \"), \" item-title \")]/h1" }, { "accept_selectors": [ ".name > .profile_link" ], "container_id": "bf9e-40b6-959f", "data": { "dca8-4ea1-a738": { "attribute": "href", "extractors": {}, "field": "5983-4b80-8547", "required": false } }, "id": "3f30-4f33-b79c", "text-content": "content", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "repeated": true, "selection_mode": "css", "selector": ".profile_link", "tagid": null, "xpath": "//*[contains(concat(\" \", @class, \" \"), \" name \")]/*[contains(concat(\" \", @class, \" \"), \" profile_link \")]" }, { "accept_selectors": [ ".topics > .content > a" ], "container_id": "bf9e-40b6-959f", "data": { "e7cf-4930-aaf2": { "attribute": "content", "extractors": {}, "field": "5ccf-4bba-92c1", "required": false } }, "id": "7a51-40cc-b792", "text-content": "content", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "repeated": true, "selection_mode": "css", "selector": ".topics > .content > a", "tagid": null, "xpath": "//*[contains(concat(\" \", @class, \" \"), \" topics \")]/*[contains(concat(\" \", @class, \" \"), \" content \")]/a" } ] } }, "results": [{ "_type": "4", "title": [ "\u05d0\u05d9\u05da \u05d4\u05d4\u05e8\u05d2\u05e9\u05d4 \u05d6\u05d4 \u05dc\u05d4\u05d9\u05d5\u05ea \u05d8\u05d1\u05e2\u05d5\u05e0\u05d9?" ], "url": "http://url", "field2": [ "/profile.asp?id=139445", "/profile.asp?id=110198", "/profile.asp?id=110198", "/profile.asp?id=221475" ], "tags": [ "\u05d8\u05d1\u05e2\u05d5\u05e0\u05d9\u05d9\u05dd", "\u05d8\u05d1\u05e2\u05d5\u05e0\u05d5\u05ea", "\u05e8\u05d2\u05e9\u05d5\u05ea" ], "_template": "3fd3-4288-b3dd" }], "schemas": { "2cdc-4284-ab08": { "fields": { "22a1-4765-82a1": { "id": "22a1-4765-82a1", "name": "title", "required": false, "type": "text", "vary": false }, "dc27-4087-8fb8": { "id": "dc27-4087-8fb8", "name": "link", "required": false, "type": "url", "vary": false }, "779a-439b-9272": { "id": "779a-439b-9272", "name": "field1", "required": false, "type": "url", "vary": false }, "5983-4b80-8547": { "auto_created": true, "id": "5983-4b80-8547", "name": "field2", "required": false, "type": "text", "vary": false }, "5ccf-4bba-92c1": { "id": "5ccf-4bba-92c1", "name": "tags", "required": false, "type": "text", "vary": false } }, "name": "4" } }, "scrapes": "2cdc-4284-ab08", "spider": "stips.co.il_2", "url": "https://stips.co.il/ask/5163110/%D7%90%D7%99%D7%9A-%D7%94%D7%94%D7%A8%D7%92%D7%A9%D7%94-%D7%96%D7%94-%D7%9C%D7%94%D7%99%D7%95%D7%AA-%D7%98%D7%91%D7%A2%D7%95%D7%A0%D7%99", "version": "0.13.0b35" } ================================================ FILE: slybot/slybot/tests/data/templates/xceed.json ================================================ { "allowed_domains": [], "exclude_patterns": [], "follow_patterns": [ "/events/[\\w\\-]+", "/clubs-in-[\\w-]+", "/tickets-club/[\\w\\-]+", "/events/[\\w\\-]+/\\d+" ], "id": "xceed.me", "items": { "21d4-4268-85cd": { "fields": { "0885-44ad-8d18": { "name": "name", "required": false, "type": "text", "vary": false }, "3d00-45e4-a1ec": { "name": "cover", "required": false, "type": "image", "vary": false }, "51ea-4fcb-a355": { "name": "location", "required": false, "type": "text", "vary": false }, "54fe-468e-b804": { "name": "text", "required": false, "type": "text", "vary": false }, "93f8-405c-a546": { "name": "time", "required": false, "type": "text", "vary": false }, "b1da-4d02-b590": { "name": "date", "required": false, "type": "text", "vary": false } }, "name": "event" }, "290f-4500-acc8": { "fields": { "799f-4875-b9dc": { "name": "image", "required": false, "type": "image", "vary": false }, "df47-43f9-aa35": { "name": "name", "required": false, "type": "text", "vary": false }, "e525-4f50-b864": { "name": "address", "required": false, "type": "text", "vary": false } }, "name": "venue" }, "6744-4764-b73b": { "fields": { "1b58-4551-a224": { "name": "type", "required": false, "type": "text", "vary": false }, "4ed4-4fa6-ade1": { "name": "includes", "required": false, "type": "text", "vary": false }, "53cc-4161-8678": { "name": "Pay", "required": false, "type": "text", "vary": false }, "a794-43f5-9378": { "name": "price", "required": false, "type": "price", "vary": false }, "ee83-4d06-aec6": { "name": "date", "required": false, "type": "text", "vary": false } }, "name": "ticket" } }, "js_disable_patterns": [], "js_enable_patterns": [], "js_enabled": false, "links_to_follow": "patterns", "name": "xceed.me", "project": "35182", "respect_nofollow": false, "results": [ { "_index": 1, "_template": "ec891c9df77d09298c0f44f7973af3d5d4adc1e5", "_type": "ticket", "date": [ "Sales end: Jun 10, 23:45pm" ], "includes": [ "+ 1 Copa Inlc. hasta las 02.30 / 1 Long Drink Incl, untill 02.30" ], "price": [ "13.00" ], "type": [ "Guest List" ], "url": "http://url" }, { "_index": 2, "_template": "ec891c9df77d09298c0f44f7973af3d5d4adc1e5", "_type": "ticket", "date": [ "Sales end: Jun 09, 14:00pm" ], "includes": [ "Early Bird! - Long Drink incl / Copa Incl." ], "price": [ "15.00" ], "type": [ "Ticket" ], "url": "http://url" }, { "_index": 3, "_template": "ec891c9df77d09298c0f44f7973af3d5d4adc1e5", "_type": "ticket", "date": [ "Sales end: Jun 10, 23:45pm" ], "includes": [ "+ 1 Copa Inlc. / 1 Long Drink Incl," ], "price": [ "18.00" ], "type": [ "Ticket" ], "url": "http://url" }, { "_index": 4, "_template": "ec891c9df77d09298c0f44f7973af3d5d4adc1e5", "_type": "ticket", "date": [ "Sales end: Jun 10, 23:45pm" ], "includes": [ "Prive\u00e9 on the Dance Floor for 5 people - 1 bottle inc. + soft drinks" ], "price": [ "200.00" ], "type": [ "Bottle Service" ], "url": "http://url" }, { "_index": 5, "_template": "ec891c9df77d09298c0f44f7973af3d5d4adc1e5", "_type": "ticket", "date": [ "Sales end: Jun 10, 23:45pm" ], "includes": [ "Prive\u00e9 on the Backstage for 5 people - 1 bottle inc. + soft drinks" ], "price": [ "230.00" ], "type": [ "Bottle Service" ], "url": "http://url" }, { "_template": "ec891c9df77d09298c0f44f7973af3d5d4adc1e5", "_type": "venue", "address": [ "Poble Espanyol , Barcelona , Spain" ], "image": [ "https://res.cloudinary.com/xceed-me/image/upload/f_auto,h_150,w_150/v1464098101/venues/logo/55c867d73589f.jpg.jpg" ], "name": [ "La Terrrazza" ], "url": "http://url" }, { "_template": "ec891c9df77d09298c0f44f7973af3d5d4adc1e5", "_type": "event", "cover": [ "https://res.cloudinary.com/xceed-me/image/upload/f_auto/v1464098101/events/cover/e0e1b7d7b5fb44d760e3c7e46fb127.png.jpg" ], "date": [ "Friday, 10 June 2016" ], "location": [ "La Terrrazza - Barcelona, Spain" ], "name": [ "Cover F.U.N. at La Terrrazza with Cristoph | Neil Daruwala | Jade Rolt" ], "text": [ "F.U.N. at La Terrrazza with Cristoph | Neil Daruwala | Jade Rolt" ], "time": [ "From 23:45 to 6:00" ], "url": "http://url" } ], "start_urls": [ "https://xceed.me/" ], "templates": [ { "extractors": {}, "id": "64d9-49f1-8c07", "name": "event", "original_body": "F.U.N. at La Terrrazza with | La Terrrazza - Barcelona | 10 June
    \"Cover
    06/10/2016 23:4506/11/2016 06:00Europe/MadridF.U.N. at La Terrrazza with Cristoph | Neil Daruwala | Jade RoltEvery Friday is the Unexpected Night with International Guest Dj's at La TerrrazzaLa Terrrazza, BarcelonafalseMM/DD/YYYY

    \n From 23:45 to 6:00\n

    F.U.N. at La Terrrazza with Cristoph | Neil Daruwala | Jade Rolt

    La Terrrazza - Barcelona, Spain
    Tech houseDeep HouseTech houseDeep House
    Ticket type
    Price
    Quantity

    \n Guest List\n

    + 1 Copa Inlc. hasta las 02.30 / 1 Long Drink Incl, untill 02.30

    \u20ac13.00

    Pay at the door

    Sales end: Jun 10, 23:45pm

    \n Ticket \n

    Early Bird! - Long Drink incl / Copa Incl.

    \u20ac15.00

    Sales end: Jun 09, 14:00pm

    \n Ticket \n

    + 1 Copa Inlc. / 1 Long Drink Incl,

    \u20ac18.00

    Sales end: Jun 10, 23:45pm

    \n Bottle Service \n

    Prive\u00e9 on the Dance Floor for 5 people - 1 bottle inc. + soft drinks

    \u20ac200.00

    Sales end: Jun 10, 23:45pm

    \n Bottle Service \n

    Prive\u00e9 on the Backstage for 5 people - 1 bottle inc. + soft drinks

    \u20ac230.00

    Sales end: Jun 10, 23:45pm

    Service fee

    TOTAL AMOUNT

    Taxes included

    LINE UP

    CristophNeil DaruwalaJade RoltCristophNeil DaruwalaJade Rolt

    Atmosphere

    \n International\n - Outdoor\n

    Door Policy

    \n Smart Casual dress code. \n +18

    DESCRIPTION

    Every Friday is the Unexpected Night with International Guest Dj's at La Terrrazza

    \"La

    La Terrrazza

    Poble Espanyol, Barcelona, Spain

    La Terrrazza is an incredible open-air club inside a beautiful walled replica village (Pueblo Espa\u00f1ol) nestled at the side of Barcelona\u2019s famous Montjuic Hill where masses of international and resident DJs have played since it opened 20 years ago. It has often been named within the top 50 best clubs in the world and is open for the summer season from May until October. House, electronica and techno, with a taste of Balearic sounds, are the main musical genres one can expect to hear at their fantastic parties. Many famous names have played there throughout the years, some worthy of mention include Richie Hawtin and Ricardo Villalobos. Entry +18 years of age. The club reserves the right of admission.

    \"Image
    \"Image
    \"Image
    \"Image
    \"Image
    \"Image
    \"Image
    \"Image
    ", "page_id": "ec891c9df77d09298c0f44f7973af3d5d4adc1e5", "page_type": "item", "plugins": { "annotations-plugin": { "extracts": [ { "accept_selectors": [ "#cover > .height-auto" ], "container_id": "770c-4cd7-a787", "data": { "0e85-49c0-a8e0": { "attribute": "src", "extractors": {}, "field": "3d00-45e4-a1ec", "required": false } }, "id": "d391-44fb-b74e", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": "main > div > figure > .height-auto", "tagid": null }, { "accept_selectors": [ "#cover > .height-auto" ], "container_id": "770c-4cd7-a787", "data": { "bec8-4401-8f55": { "attribute": "alt", "extractors": {}, "field": "0885-44ad-8d18", "required": false } }, "id": "57bb-41ce-a5c9", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": "main > div > figure > .height-auto", "tagid": null }, { "accept_selectors": [ "h1" ], "container_id": "770c-4cd7-a787", "data": { "af93-4af3-bbd5": { "attribute": "content", "extractors": {}, "field": "54fe-468e-b804", "required": false } }, "id": "f910-4e47-81b8", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": "main > div > section:nth-child(4) > h1", "tagid": null }, { "accept_selectors": [ "time" ], "container_id": "770c-4cd7-a787", "data": { "87a5-4d80-896e": { "attribute": "content", "extractors": {}, "field": "b1da-4d02-b590", "required": false } }, "id": "17df-4f30-90f5", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": "main > div > .col-md-6 > .addeventatc > p:nth-child(9) > time", "tagid": null }, { "accept_selectors": [ "p:nth-child(10)" ], "container_id": "770c-4cd7-a787", "data": { "6e4f-4c38-9fbc": { "attribute": "content", "extractors": {}, "field": "93f8-405c-a546", "required": false } }, "id": "abf2-48cb-b4e6", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": "main > div > .col-md-6 > .addeventatc > .small", "tagid": null }, { "accept_selectors": [ ".location:nth-child(2)" ], "container_id": "770c-4cd7-a787", "data": { "8640-44d1-8e72": { "attribute": "content", "extractors": {}, "field": "51ea-4fcb-a355", "required": false } }, "id": "48bb-4e8d-af8c", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": "main > div > section:nth-child(4) > .location", "tagid": null }, { "accept_selectors": [ "main > div" ], "annotations": { "#portia-content": "#dummy" }, "container_id": null, "id": "770c-4cd7-a787", "item_container": true, "reject_selectors": [], "repeated": false, "required": [], "schema_id": "21d4-4268-85cd", "selector": "main > div", "siblings": 0, "tagid": 70, "text-content": "#portia-content" }, { "accept_selectors": [ "#venue-event" ], "annotations": { "#portia-content": "#dummy" }, "container_id": null, "field": null, "id": "72b0-4bd7-85e2", "item_container": true, "required": [], "schema_id": "290f-4500-acc8", "selector": "#venue-event", "text-content": "#portia-content" }, { "accept_selectors": [ ".venue-logo" ], "container_id": "72b0-4bd7-85e2", "data": { "6a2a-40a4-86ef": { "attribute": "src", "extractors": {}, "field": "799f-4875-b9dc", "required": false } }, "id": "79fa-410e-9528", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": "#venue-event > .col-xs-3 > a > .height-auto", "tagid": null }, { "accept_selectors": [ "#venue-name > a" ], "container_id": "72b0-4bd7-85e2", "data": { "90c2-4acc-aa36": { "attribute": "content", "extractors": [], "field": "df47-43f9-aa35", "required": false } }, "id": "b393-4844-bd4f", "reject_selectors": [], "required": [], "selector": "#venue-name > a", "tagid": null }, { "accept_selectors": [ "#venue-address" ], "container_id": "72b0-4bd7-85e2", "data": { "dfbb-4a6f-8dc8": { "attribute": "content", "extractors": [], "field": "e525-4f50-b864", "required": false } }, "id": "9971-4cde-bec6", "reject_selectors": [], "required": [], "selector": "#venue-address", "tagid": null }, { "accept_selectors": [ ".data" ], "annotations": { "#portia-content": "#dummy" }, "container_id": "67f7-47df-b3d2#parent", "field": null, "id": "67f7-47df-b3d2", "item_container": true, "repeated": true, "required": [], "schema_id": "6744-4764-b73b", "selector": ".data", "siblings": 0, "text-content": "#portia-content" }, { "accept_selectors": [ ".data:nth-child(5) > .price > p:nth-child(3)", ".data:nth-child(6) > .price > p" ], "container_id": "67f7-47df-b3d2", "data": { "3467-4d54-8814": { "attribute": "content", "extractors": {}, "field": "a794-43f5-9378", "required": false } }, "id": "bcc8-44b0-b0e1", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": ".data > .price > p:nth-child(3)", "tagid": null }, { "accept_selectors": [ "#data" ], "annotations": { "#portia-content": "#dummy" }, "container_id": null, "field": null, "id": "67f7-47df-b3d2#parent", "item_container": true, "repeated": false, "required": [], "schema_id": "6744-4764-b73b", "selector": "#data", "siblings": 0, "text-content": "#portia-content" }, { "accept_selectors": [ ".data:nth-child(5) > .type > p:nth-child(1)" ], "container_id": "67f7-47df-b3d2", "data": { "aebd-4b36-a1fd": { "attribute": "content", "extractors": {}, "field": "1b58-4551-a224", "required": false } }, "id": "6ad7-4e63-8ebd", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": ".data > .type > p:nth-child(1)", "tagid": null }, { "accept_selectors": [ ".data:nth-child(5) > .type > .small" ], "container_id": "67f7-47df-b3d2", "data": { "4c4c-4618-8390": { "attribute": "content", "extractors": {}, "field": "4ed4-4fa6-ade1", "required": false } }, "id": "dd46-465e-9aa0", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": ".data > .type > .small", "tagid": null }, { "accept_selectors": [ ".data:nth-child(5) > .quantity > .small" ], "container_id": "67f7-47df-b3d2", "data": { "800d-4052-9842": { "attribute": "content", "extractors": {}, "field": "ee83-4d06-aec6", "required": false } }, "id": "e5c9-4b71-be28", "post_text": null, "pre_text": null, "reject_selectors": [], "required": [], "selection_mode": "auto", "selector": ".data > .quantity > .small", "tagid": null } ] } }, "scrapes": "74f1-4fb3-83e0", "spider": "xceed.me", "url": "https://xceed.me/events/barcelona/17652/f-u-n-at-la-terrrazza-with-cristoph-neil-daruwala-jade-rolt", "version": "0.13.0b18" } ] } ================================================ FILE: slybot/slybot/tests/data/test_params.txt ================================================ Cars Boats ================================================ FILE: slybot/slybot/tests/test_baseurl.py ================================================ """ Tests for apply_annotations """ from unittest import TestCase from slybot.baseurl import insert_base_url, get_base_url from scrapely.htmlpage import HtmlPage class TestApplyAnnotations(TestCase): def test_insert_base_relative(self): """Replace relative base href""" html_in = '' html_target = '\ ' html_out = insert_base_url(html_in, "http://localhost:8000/") self.assertEqual(html_out, html_target) def test_insert_base_noreplace(self): """base tag dont need to be replaced""" html_in = html_target = '' html_out = insert_base_url(html_in, "http://localhost:8000/users/blog.html") self.assertEqual(html_out, html_target) def test_insert_base_addbase(self): """add base tag when not present""" html_in = '\ ' html_target = '\ \ ' html_out = insert_base_url(html_in, "http://localhost:8000/") self.assertEqual(html_out, html_target) def test_insert_base_commented(self): """Test weird case when base tag is commented in origin""" html_in = '\ Body' html_target = '\ Body' html_out = insert_base_url(html_in, "http://example.com/") self.assertEqual(html_out, html_target) def test_insert_base_nohead(self): """Test base insert when no head element is present""" html_in = 'Body' html_target = '\n\ \n\ Body' html_out = insert_base_url(html_in, "http://localhost:8000/") self.assertEqual(html_out, html_target) def test_get_base_url(self): """Basic get_base_url test""" html = u'\ ' page = HtmlPage("http://example.com/products/p19.html", body=html) self.assertEqual(get_base_url(page), "http://example.com/products/") def test_get_base_url_nobase(self): """Base tag does not exists""" html = u'' page = HtmlPage("http://example.com/products/p19.html", body=html) self.assertEqual(get_base_url(page), "http://example.com/products/p19.html") def test_get_base_url_empty_basehref(self): """Base tag exists but href is empty""" html = u'\ ' url = "http://example.com/products/p19.html" page = HtmlPage(url, body=html) self.assertEqual(get_base_url(page), url) ================================================ FILE: slybot/slybot/tests/test_dropmeta.py ================================================ # -*- coding: utf-8 -*- from unittest import TestCase from scrapy.settings import Settings from slybot.spidermanager import SlybotSpiderManager from slybot.meta import DropMetaPipeline from .utils import PATH class DropMetaTest(TestCase): def test_dupefilter(self): smanager = SlybotSpiderManager("%s/data/SampleProject" % PATH) name = 'books.toscrape.com' spider = smanager.create(name) spec = smanager._specs["spiders"][name] dropmeta = DropMetaPipeline(Settings({"SLYDROPMETA_ENABLED": True})) result = { "breadcrumbs": ["Home", "Books", "Mystery"], "description": [ u"WICKED above her hipbone, GIRL across her heart Words are " u"like a road map to reporter Camille Preaker’s troubled past." u" Fresh from a brief stay at a psych hospital, Camille’s " u"first assignment from the second-rate daily paper where she " u"works brings her reluctantly back to her hometown to cover " u"the murders of two preteen girls. NASTY on her kneecap, " u"BABYDOLL on her leg Since WICKED above her hipbone, GIRL " u"across her heart Words are like a road map to reporter " u"Camille Preaker’s troubled past. Fresh from a brief stay at " u"a psych hospital, Camille’s first assignment from the " u"second-rate daily paper where she works brings her " u"reluctantly back to her hometown to cover the murders of " u"two preteen girls. NASTY on her kneecap, BABYDOLL on her leg" u" Since she left town eight years ago, Camille has hardly " u"spoken to her neurotic, hypochondriac mother or to the " u"half-sister she barely knows: a beautiful thirteen-year-old " u"with an eerie grip on the town. Now, installed again in her " u"family’s Victorian mansion, Camille is haunted by the " u"childhood tragedy she has spent her whole life trying to cut" u" from her memory. HARMFUL on her wrist, WHORE on her ankle " u"As Camille works to uncover the truth about these violent " u"crimes, she finds herself identifying with the young " u"victims—a bit too strongly. Clues keep leading to dead ends," u" forcing Camille to unravel the psychological puzzle of her " u"own past to get at the story. Dogged by her own demons, " u"Camille will have to confront what happened to her years " u"before if she wants to survive this homecoming.With its " u"taut, crafted writing, Sharp Objects is addictive, haunting," u" and unforgettable. ...more" ], "image": [ "http://books.toscrape.com/media/cache/c0/59/c05972805aa720117" "1b8fc71a5b00292.jpg" ], "info": { "price": ["47.82"], "stock": ["20"], "tax": ["0.00"], "type": ["Books"], "upc": ["e00eb4fd7b871a48"]}, "url": ("http://books.toscrape.com/catalogue/" "sharp-objects_997/index.html") } tid = '3617-44af-a2f0' extracted = next(t for t in spec["templates"] if t['page_id'] == tid) processed = dropmeta.process_item(extracted['results'][0], spider) self.assertEqual(result, processed) ================================================ FILE: slybot/slybot/tests/test_dupefilter.py ================================================ from unittest import TestCase from os.path import dirname from scrapy.http import HtmlResponse from scrapy.settings import Settings from scrapy.item import DictItem from scrapy.exceptions import DropItem from slybot.spidermanager import SlybotSpiderManager from slybot.dupefilter import DupeFilterPipeline _PATH = dirname(__file__) class DupeFilterTest(TestCase): smanager = SlybotSpiderManager("%s/data/SampleProject" % _PATH) def test_dupefilter(self): name = "seedsofchange2" spider = self.smanager.create(name) spec = self.smanager._specs["spiders"][name] t1, t2 = spec["templates"] dupefilter = DupeFilterPipeline(Settings({"SLYDUPEFILTER_ENABLED": True})) response1 = HtmlResponse(url=t1["url"], body=t1["original_body"].encode('utf-8')) response2 = HtmlResponse(url=t2["url"], body=t2["original_body"].encode('utf-8')) result1 = spider.handle_html(response1) for item1 in result1: if isinstance(item1, DictItem): break result2 = spider.handle_html(response2) for item2 in result2: if isinstance(item2, DictItem): break self.assertEqual(item1, dupefilter.process_item(item1, spider)) self.assertEqual(item2, dupefilter.process_item(item2, spider)) self.assertRaises(DropItem, dupefilter.process_item, item1, spider) ================================================ FILE: slybot/slybot/tests/test_extraction_speed.py ================================================ import json import os from os.path import dirname from collections import namedtuple from unittest import TestCase from slybot.item import create_slybot_item_descriptor from slybot.utils import read from slybot.plugins.scrapely_annotations.extraction import ( SlybotIBLExtractor, BaseContainerExtractor) from scrapy.selector.unified import SelectorList, Selector from scrapely.extraction.pageobjects import TokenDict from scrapely.htmlpage import HtmlPage def _next_3(iterable): i = iter(iterable[1:-3]) while True: try: yield SelectorList((next(i), next(i), next(i))) except StopIteration: break ITERATIONS = int(os.environ.get('SLYBOT_SPEED_TEST_ITERATIONS', 1)) Extractor = namedtuple('Extractor', ['containers', 'selectors', 'group']) parsel_extractors = { 'daft': Extractor('//div[@class="box"]', {u'name': './/h2/a/text()', u'price': './/strong[@class="price"]/text()', u'description': './/div[@class="text-block"]/p/text()', u'url': './/h2/a/@href'}, None), 'hn': Extractor('//table//table//tr', {u'name': './/td[@class="title"]/a/text()', u'price': './/td/span[contains(@id,"score")]/text()', u'description': './/td/span/a//text()', u'url': './/td[@class="title"]/a/@href'}, _next_3), 'pol': Extractor('//div[contains(@class, "item")]', {u'name': './/div[@class="product-image"]/a/@title', u'price': './/li[@class="fund"]/strong/text()', u'description': './/div[@class="descbox"]/ul', u'url': './/div[@class="product-image"]/a/@href', u'product_id': './/div[@class="product-image"]/a/@id'}, None) } def extract(extractor, selector): items = [] item_selectors = selector.xpath(extractor.containers) if extractor.group: item_selectors = extractor.group(item_selectors) for row in item_selectors: item = {k: row.xpath(xpath).extract() for k, xpath in extractor.selectors.items()} item = {k: v for k, v in item.items() if v} validated = validate(item, html_page) if not validated: continue if hasattr(validated, 'dump'): validated = validated.dump() validated['_template'] = None items.append(validated) items = list(filter(bool, items)) return [i for i in items if '_type' in i] _PATH = dirname(__file__) td = TokenDict() with open('%s/data/SampleProject/items.json' % _PATH) as f: items = json.load(f) descriptors = {'#default': create_slybot_item_descriptor(items['default'], 'default')} class FakeContainer(BaseContainerExtractor): def __init__(self, schema, legacy=False): self.schema = schema self.extra_requires = [] self.legacy = legacy self.modifiers = {} schema = FakeContainer(descriptors['#default']) validate = schema._validate_and_adapt_item _names_map = {'daft_ie': 'daft', 'patchofland': 'pol'} ibl_extractors = {} ibl_pages = {} selector_pages = {} for template_name in ('daft_ie', 'hn', 'patchofland'): with open('%s/data/templates/%s.html' % (_PATH, template_name), 'rb') as f: html_page = HtmlPage(body=read(f)) name = _names_map.get(template_name, template_name) ibl_pages[name] = html_page ibl_extractors[name] = SlybotIBLExtractor([(html_page, descriptors, '0.13.0')]) selector_pages[name] = Selector(text=html_page.body) class TestExtractionSpeed(TestCase): def test_parsel_parse_and_extract(self): for i in range(ITERATIONS): for name, page in ibl_pages.items(): s = Selector(text=page.body) extract(parsel_extractors[name], s) def test_slybot_parse_and_extract(self): for i in range(ITERATIONS): for name, page in ibl_pages.items(): extraction_page = HtmlPage(body=page.body) ibl_extractors[name].extract(extraction_page) def test_parsel_extract(self): for i in range(ITERATIONS): for name, page in ibl_pages.items(): extract(parsel_extractors[name], selector_pages[name]) def test_slybot_extract(self): for i in range(ITERATIONS): for name, page in ibl_pages.items(): ibl_extractors[name].extract(page) ================================================ FILE: slybot/slybot/tests/test_extractors.py ================================================ from unittest import TestCase from datetime import datetime from scrapely.htmlpage import HtmlPage from scrapely.extraction import InstanceBasedLearningExtractor from slybot.extractors import (create_regex_extractor, apply_extractors, add_extractors_to_descriptors) from slybot.fieldtypes import TextFieldTypeProcessor from slybot.item import create_slybot_item_descriptor from slybot.plugins.scrapely_annotations.extraction import SlybotIBLExtractor from slybot.plugins.scrapely_annotations.builder import ( Annotations, _clean_annotation_data ) class ExtractorTest(TestCase): annotated = u"""
    Gender Male
    """ _target = u"""
    Gender Male
    """ annotated2 = u""" Male
    Name John
    """ _target2 = u""" NameOlivia """ annotations = _clean_annotation_data([{ 'id': 'annotation1', 'selector': 'td > a', 'container_id': 'parent', 'data': { 1: { 'attribute': 'content', 'field': 'title', 'required': False, 'extractors': [] }, 2: { 'attribute': 'content', 'field': 'name', 'required': False, 'extractors': ['3'] }, 3: { 'attribute': 'href', 'field': 'url', 'required': False, 'extractors': ['1', '2'] } } }, { 'id': 'annotation2', 'selector': 'span', 'container_id': 'parent', 'data': { 1: { 'attribute': 'content', 'field': 'price', 'required': False, 'extractors': ['8', '4', '5', '6'] }, 2: { 'attribute': 'content', 'field': 'date', 'required': False, 'extractors': ['4', '7'] } } }, { 'id': 'parent', 'item_container': True, 'selector': 'body' }]) target3 = u""" Name Name: Olivia 2016-03-17 20:25 """ template = HtmlPage(url="http://www.test.com/", body=annotated) target = HtmlPage(url="http://www.test.com/", body=_target) template2 = HtmlPage(url="http://www.test.com/", body=annotated2) target2 = HtmlPage(url="http://www.test.com/a", body=_target2) sample3 = {'plugins': {'annotations-plugin': {'extracts': annotations}}, 'original_body': target3} template3 = HtmlPage(url="http://www.test.com/a", body=Annotations(sample3).apply()) target3 = HtmlPage(url="http://www.test.com/a", body=target3) def test_regex_extractor(self): extractor = create_regex_extractor("(\d+).*(\.\d+)") extracted = extractor(u"The price of this product is
    45
    .50 pounds") self.assertEqual(extracted, u"45.50") processor = TextFieldTypeProcessor() self.assertEqual(processor.adapt(extracted, None), u"45.50") def test_raw_type_w_regex(self): schema = { 'fields': { 'gender': { 'required': False, 'type': 'raw', 'vary': False, } } } descriptor = create_slybot_item_descriptor(schema) extractors = { 1: {"regular_expression": "Gender.*((?:Male|Female))"} } apply_extractors(descriptor, {"gender": [1]}, extractors) ibl_extractor = SlybotIBLExtractor([ (self.template, {'#default': descriptor}, '0.12.0')]) self.assertEqual(ibl_extractor.extract(self.target)[0][0]['gender'], [u'Male']) def test_negative_hit_w_regex(self): schema = { 'fields': { 'gender': { 'required': False, 'type': 'number', 'vary': False, } } } descriptor = create_slybot_item_descriptor(schema) extractors = {1: {"regular_expression": "Gender\\s+(Male|Female)"}} apply_extractors(descriptor, {"gender": [1]}, extractors) ibl_extractor = SlybotIBLExtractor([ (self.template, {'#default': descriptor}, '0.12.0')]) self.assertEqual(ibl_extractor.extract(self.target)[0], None) def test_text_type_w_regex(self): schema = { "fields": { 'gender': { 'required': False, 'type': 'text', 'vary': False, } } } descriptor = create_slybot_item_descriptor(schema) extractors = {1: {"regular_expression": "Gender\\s+(Male|Female)"}} apply_extractors(descriptor, {"gender": [1]}, extractors) ibl_extractor = SlybotIBLExtractor([ (self.template, {'#default': descriptor}, '0.12.0')]) self.assertEqual(ibl_extractor.extract(self.target)[0][0]['gender'], [u'Male']) def test_type_extractor(self): schema = { "fields": { 'gender': { 'required': False, 'type': 'number', 'vary': False, } } } descriptor = create_slybot_item_descriptor(schema) extractors = { 1: {"type_extractor": "text"}, 2: {"regular_expression": "Gender\\s+(Male|Female)"} } apply_extractors(descriptor, {"gender": [1, 2]}, extractors) ibl_extractor = SlybotIBLExtractor([ (self.template, {'#default': descriptor}, '0.12.0')]) self.assertEqual(ibl_extractor.extract(self.target)[0][0]['gender'], [u'Male']) def test_default_type_extractor(self): schema = { 'fields': {} } descriptor = create_slybot_item_descriptor(schema) extractors = { 1: {"regular_expression": "Gender\\s+(Male|Female)"} } apply_extractors(descriptor, {"gender": [1]}, extractors) ibl_extractor = SlybotIBLExtractor([ (self.template, {'#default': descriptor}, '0.12.0')]) self.assertEqual(ibl_extractor.extract(self.target)[0][0]['gender'], [u'Male']) def test_text_type_w_regex_and_no_groups(self): schema = { 'fields': { 'gender': { 'required': False, 'type': 'text', 'vary': False, } } } descriptor = create_slybot_item_descriptor(schema) extractors = { 1: {"regular_expression": "Gender"} } apply_extractors(descriptor, {"gender": [1]}, extractors) ibl_extractor = SlybotIBLExtractor([ (self.template, {'#default': descriptor}, '0.12.0')]) self.assertEqual(ibl_extractor.extract(self.target)[0][0]['gender'], [u'Gender']) def test_extractor_w_empty_string_extraction(self): schema = { 'fields': { 'gender': { 'required': False, 'type': 'text', 'vary': False, }, 'name': { 'required': True, 'type': 'text', 'vary': False, } } } descriptor = create_slybot_item_descriptor(schema) extractors = { 1: { "regular_expression": "([0-9]+)" } } apply_extractors(descriptor, {"gender": [1]}, extractors) ibl_extractor = SlybotIBLExtractor([ (self.template2, {'#default': descriptor}, '0.12.0')]) self.assertEqual(ibl_extractor.extract(self.target2)[0][0]['name'], [u'Name Olivia']) def test_per_annotation_extractors(self): schema = { 'fields': { 'url': { 'required': False, 'type': 'text', 'vary': False, }, 'name': { 'required': True, 'type': 'text', 'vary': False, } } } extractors = { '1': { 'type_extractor': 'url' }, '2': { 'regular_expression': '(.*)\.html' }, '3': { 'regular_expression': 'Name: (.*)' }, '4': { 'type_extractor': 'text' }, '5': { 'type_extractor': 'price' }, '6': { 'type_extractor': 'number' }, '7': { 'type_extractor': 'date' }, '8': { 'regular_expression': '(\d+)-' } } descriptors = {'#default': create_slybot_item_descriptor(schema)} add_extractors_to_descriptors(descriptors, extractors) ibl_extractor = SlybotIBLExtractor([ (self.template3, descriptors, '0.13.0') ]) result = {u'_template': '6223d000057491040e4f411cf1f0734ea802eeb6', 'name': [u'Olivia'], 'url': [u'http://www.test.com/olivia'], 'title': [u'Name: Olivia'], 'price': [u'2016'], 'date': [datetime(2016, 3, 17, 20, 25)]} data = ibl_extractor.extract(self.target3)[0][0] self.assertEqual(data, result) ================================================ FILE: slybot/slybot/tests/test_fieldtypes.py ================================================ from unittest import TestCase from scrapely.htmlpage import HtmlPage from slybot.fieldtypes import UrlFieldTypeProcessor, ImagesFieldTypeProcessor class FieldTypesUrlEncoding(TestCase): def test_not_standard_chars_in_url(self): body = u'' url = u'fotos/produtos/Mam\xe3e noel.jpg' htmlpage = HtmlPage(url=u"http://www.example.com/", body=body, encoding='cp1252') processor = UrlFieldTypeProcessor() self.assertEqual(processor.adapt(url, htmlpage), u'http://www.example.com/fotos/produtos/Mam%C3%A3e%20noel.jpg') def test_uri_stripped_of_whitespace_and_quote_characters_correctly(self): urls = [u' image.jpg ', u" '/data.jpg'", u'\n\t"file.jpg"\n\t\t'] results = ['http://www.example.com/images/image.jpg', 'http://www.example.com/data.jpg', 'http://www.example.com/images/file.jpg'] htmlpage = HtmlPage(url=u"http://www.example.com/images/", body=u'', encoding='utf-8') url_p = UrlFieldTypeProcessor() img_p = ImagesFieldTypeProcessor() for text, url in zip(urls, results): self.assertEqual(img_p.adapt(img_p.extract(text), htmlpage), url) self.assertEqual(url_p.adapt(url_p.extract(text), htmlpage), url) def test_uri_with_illegal_html_entities(self): urls = [u' image.jpg ', u" '/ �data.jpg'", u'\n\t"file.jpg"\n\t\t'] results = ['http://www.example.com/images/image.jpg', 'http://www.example.com/data.jpg', 'http://www.example.com/images/file.jpg'] htmlpage = HtmlPage(url=u"http://www.example.com/images/", body=u'', encoding='utf-8') url_p = UrlFieldTypeProcessor() img_p = ImagesFieldTypeProcessor() for text, url in zip(urls, results): self.assertEqual(img_p.adapt(img_p.extract(text), htmlpage), url) self.assertEqual(url_p.adapt(url_p.extract(text), htmlpage), url) def test_blank_image_url(self): assert ImagesFieldTypeProcessor().extract(' ') == '' ================================================ FILE: slybot/slybot/tests/test_fragment_generator.py ================================================ from unittest import TestCase from slybot.starturls import FragmentGenerator class FragmentGeneratorTest(TestCase): def test_generated_url_list(self): github_start_urls = [ 'https://github.com/scrapinghub', 'https://github.com/scrapy', 'https://github.com/scrapy-plugins' ] url_spec = { 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, {'type': 'list', 'value': 'scrapinghub scrapy scrapy-plugins'}, ] } generator = FragmentGenerator() self.assertEqual(list(generator(url_spec)), github_start_urls) def test_generated_url_range(self): github_start_urls = [ 'https://github.com/0', 'https://github.com/1', 'https://github.com/2' ] url_spec = { 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, {'type': 'range', 'value': '0-2'}, ] } generator = FragmentGenerator() self.assertEqual(list(generator(url_spec)), github_start_urls) def test_mixed_fragments(self): donedeal_start_urls = [ 'https://www.donedeal.ie/cars-for-sale/i/1', 'https://www.donedeal.ie/cars-for-sale/i/2', 'https://www.donedeal.ie/houses-for-sale/i/1', 'https://www.donedeal.ie/houses-for-sale/i/2', 'https://www.donedeal.ie/pets-for-sale/i/1', 'https://www.donedeal.ie/pets-for-sale/i/2', 'https://www.donedeal.ie/kitchens-for-sale/i/1', 'https://www.donedeal.ie/kitchens-for-sale/i/2' ] url_spec = { 'fragments': [ {'type': 'fixed', 'value': 'https://www.donedeal.ie/'}, { 'type': 'list', 'value': ('cars-for-sale houses-for-sale ' 'pets-for-sale kitchens-for-sale') }, {'type': 'fixed', 'value': '/i/'}, {'type': 'range', 'value': '1-2'}, ] } generator = FragmentGenerator() self.assertEqual(list(generator(url_spec)), donedeal_start_urls) def test_generated_letters(self): github_start_urls = [ 'https://github.com/scrapinghub/a', 'https://github.com/scrapinghub/b', 'https://github.com/scrapinghub/c', 'https://github.com/scrapinghub/d', ] url_spec = { 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/scrapinghub/'}, {'type': 'range', 'value': 'a-d'}, ] } generator = FragmentGenerator() self.assertEqual(list(generator(url_spec)), github_start_urls) ================================================ FILE: slybot/slybot/tests/test_generic_form.py ================================================ import json from os.path import dirname, join from unittest import TestCase from slybot.generic_form import GenericForm from .utils import request_to_set _PATH = dirname(__file__) class GenericFormTest(TestCase): def test_simple_search_form(self): url = 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc' body = open(join(_PATH, "data", "ebay_advanced_search.html")).read() form_descriptor = json.loads("""{ "type": "form", "form_url": "http://www.ebay.com/sch/ebayadvsearch/?rt=nc", "xpath": "//form[@name='adv_search_from']", "fields": [ { "xpath": ".//*[@name='_nkw']", "type": "constants", "value": ["Cars"] } ] }""") generic_form = GenericForm() start_requests = list(generic_form.fill_generic_form(url, body, form_descriptor)) expected_requests = [([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', u'Cars'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET')] self.assertEqual(request_to_set(start_requests), request_to_set(expected_requests)) def test_simple_search_form_2_values(self): url = 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc' body = open(join(_PATH, "data", "ebay_advanced_search.html")).read() form_descriptor = json.loads("""{ "type": "form", "form_url": "http://www.ebay.com/sch/ebayadvsearch/?rt=nc", "xpath": "//form[@name='adv_search_from']", "fields": [ { "xpath": ".//*[@name='_nkw']", "type": "constants", "value": ["Cars", "Boats"] } ] }""") generic_form = GenericForm() start_requests = list(generic_form.fill_generic_form(url, body, form_descriptor)) expected_requests = [([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', u'Cars'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET'), ([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', u'Boats'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET')] self.assertEqual(request_to_set(start_requests), request_to_set(expected_requests)) def test_advanced_search_form(self): url = 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc' body = open(join(_PATH, "data", "ebay_advanced_search.html")).read() form_descriptor = json.loads("""{ "type": "form", "form_url": "http://www.ebay.com/sch/ebayadvsearch/?rt=nc", "xpath": "//form[@name='adv_search_from']", "fields": [ { "xpath": ".//*[@name='_nkw']", "type": "constants", "value": ["Cars"] }, { "xpath": ".//*[@name='_in_kw']", "type": "iterate" } ] }""") generic_form = GenericForm() start_requests = list(generic_form.fill_generic_form(url, body, form_descriptor)) expected_requests = [([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', u'Cars'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET'), ([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '2'), ('_nkw', u'Cars'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET'), ([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '3'), ('_nkw', u'Cars'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET'), ([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '4'), ('_nkw', u'Cars'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET')] self.assertEqual(request_to_set(start_requests), request_to_set(expected_requests)) def test_advanced_search_form_regex(self): url = 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc' body = open(join(_PATH, "data", "ebay_advanced_search.html")).read() form_descriptor = json.loads("""{ "type": "form", "form_url": "http://www.ebay.com/sch/ebayadvsearch/?rt=nc", "xpath": "//form[@name='adv_search_from']", "fields": [ { "xpath": ".//*[@name='_nkw']", "type": "constants", "value": ["Cars"] }, { "xpath": ".//*[@name='_in_kw']", "type": "iterate", "value": "[1-2]" } ] }""") generic_form = GenericForm() start_requests = list(generic_form.fill_generic_form(url, body, form_descriptor)) expected_requests = [([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', u'Cars'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET'), ([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '2'), ('_nkw', u'Cars'), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET')] self.assertEqual(request_to_set(start_requests), request_to_set(expected_requests)) def test_simple_search_form_with_named_parameter(self): url = 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc' body = open(join(_PATH, "data", "ebay_advanced_search.html")).read() form_descriptor = json.loads("""{ "type": "form", "form_url": "http://www.ebay.com/sch/ebayadvsearch/?rt=nc", "xpath": "//form[@name='adv_search_from']", "fields": [ { "name": "my_param", "type": "constants", "value": ["Cars"] } ] }""") generic_form = GenericForm() start_requests = list(generic_form.fill_generic_form(url, body, form_descriptor)) expected_requests = [([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), (u'my_param', u'Cars'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', ''), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET')] self.assertEqual(request_to_set(start_requests), request_to_set(expected_requests)) def test_simple_search_form_with_file_type(self): url = 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc' body = open(join(_PATH, "data", "ebay_advanced_search.html")).read() form_descriptor = json.loads("""{ "type": "form", "form_url": "http://www.ebay.com/sch/ebayadvsearch/?rt=nc", "xpath": "//form[@name='adv_search_from']", "fields": [ { "name": "my_param", "type": "inurl", "value": "file://%s/test_params.txt", "file_values": ["Cars", "Boats", "Houses", "Electronics"] } ] }""" % join(_PATH, "data")) generic_form = GenericForm() start_requests = list(generic_form.fill_generic_form(url, body, form_descriptor)) expected_requests = [([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), (u'my_param', u'Cars'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', ''), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET'), ([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), (u'my_param', u'Boats'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', ''), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET'), ([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), (u'my_param', u'Houses'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', ''), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET'), ([('_adv', '1'), ('_ex_kw', ''), ('_ftrv', '1'), ('_ftrt', '901'), ('_sabdlo', u''), ('_sabdhi', u''), ('_sop', '12'), ('_samihi', u''), ('_ipg', '50'), ('_salic', '1'), (u'my_param', u'Electronics'), ('_sasl', ''), ('_udlo', ''), ('_okw', u''), ('_fsradio', '&LH_SpecificSeller=1'), ('_udhi', ''), ('_in_kw', '1'), ('_nkw', ''), ('_sacat', '0'), ('_oexkw', u''), ('_dmd', '1'), ('_saslop', '1'), ('_samilow', u'')], 'http://www.ebay.com/sch/i.html', 'GET')] self.assertEqual(request_to_set(start_requests), request_to_set(expected_requests)) ================================================ FILE: slybot/slybot/tests/test_linkextractors.py ================================================ import json from os.path import dirname from unittest import TestCase from scrapy.http import Request from scrapy.settings import Settings from slybot.utils import htmlpage_from_response from slybot.spidermanager import SlybotSpiderManager from slybot.linkextractor import create_linkextractor_from_specs from slybot.plugins.scrapely_annotations.builder import Annotations from slybot.utils import load_plugins from slybot.spider import IblSpider from .utils import UTF8HtmlResponse, UTF8TextResponse, UTF8XmlResponse, PATH class Test_RegexLinkExtractor(TestCase): def test_default(self): specs = {"type": "regex", "value": ''} lextractor = create_linkextractor_from_specs(specs) text = "Hello http://www.example.com/path, more text https://aws.amazon.com/product?id=23#tre?" response = UTF8TextResponse(url='http://www.example.com/', body=text) links = list(lextractor.links_to_follow(response)) self.assertEqual(len(links), 2) self.assertEqual(links[0].url, 'http://www.example.com/path') self.assertEqual(links[1].url, 'https://aws.amazon.com/product?id=23') def test_custom(self): specs = {"type": "regex", "value": 'url: ((?:http|https)://www.example.com/[\w/]+)'} lextractor = create_linkextractor_from_specs(specs) text = "url: http://www.example.com/path, more text url: https://www.example.com/path2. And more text url: https://aws.amazon.com/product?id=23#tre" response = UTF8TextResponse(url='http://www.example.com/', body=text) links = list(lextractor.links_to_follow(response)) self.assertEqual(len(links), 2) self.assertEqual(links[0].url, 'http://www.example.com/path') self.assertEqual(links[1].url, 'https://www.example.com/path2') def test_custom_withargs(self): specs = {"type": "regex", "value": 'url: ((?:http|https)://www.example.com/[\w/]+)', 'allowed_schemes': ['http']} lextractor = create_linkextractor_from_specs(specs) text = "url: http://www.example.com/path, more text url: https://www.example.com/path2. And more text url: https://aws.amazon.com/product?id=23#tre" response = UTF8TextResponse(url='http://www.example.com/', body=text) links = list(lextractor.links_to_follow(response)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.example.com/path') xmlfeed = """ RSS Title This is an example of an RSS feed http://www.someexamplerssdomain.com/main.html Mon, 06 Sep 2010 00:01:00 +0000 Mon, 06 Sep 2009 16:20:00 +0000 1800 Example entry Here is some text containing an interesting description. http://www.wikipedia.org/ unique string per item Mon, 06 Sep 2009 16:20:00 +0000 """ sitemapfeed = """ http://www.accommodationforstudents.com/daily1.00 http://www.accommodationforstudents.com/London.aspdaily1.00 http://www.accommodationforstudents.com/createaccounts.aspdaily0.85 """ sitemapindex = """ http://www.example.com/sitemap1.xml.gz 2004-10-01T18:23:17+00:00 """ atomfeed = """ Example Feed A subtitle. Atom-Powered Robots Run Amok Some text. John Doe johndoe@example.com """ class Test_XmlLinkExtractors(TestCase): def setUp(self): self.response = UTF8TextResponse(url='http://www.example.com/', body=xmlfeed) self.sitemap = UTF8TextResponse(url='http://www.example.com/sitemap.xml', body=sitemapfeed) self.sitemapindex = UTF8TextResponse(url='http://www.example.com/sitemap.xml', body=sitemapindex) self.atom = UTF8TextResponse(url='http://www.example.com/atom', body=atomfeed) def test_rss(self): specs = {"type": "rss", "value": ""} lextractor = create_linkextractor_from_specs(specs) links = list(lextractor.links_to_follow(self.response)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.wikipedia.org/') def test_xml(self): specs = {"type": "xpath", "value": "//item/link/text()"} lextractor = create_linkextractor_from_specs(specs) links = list(lextractor.links_to_follow(self.response)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.wikipedia.org/') def test_sitemap(self): specs = {"type": "sitemap", "value": ""} lextractor = create_linkextractor_from_specs(specs) links = list(lextractor.links_to_follow(self.sitemap)) self.assertEqual(len(links), 3) self.assertEqual(links[0].url, 'http://www.accommodationforstudents.com/') links = list(lextractor.links_to_follow(self.sitemapindex)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.example.com/sitemap1.xml.gz') def test_atom(self): specs = {"type": "atom", "value": ""} lextractor = create_linkextractor_from_specs(specs) links = list(lextractor.links_to_follow(self.atom)) self.assertEqual(len(links), 3) self.assertEqual(links[0].url, 'http://example.org/feed/') def test_xml_remove_namespaces(self): specs = {"type": "xpath", "value": "//link/@href", "remove_namespaces": True} lextractor = create_linkextractor_from_specs(specs) links = list(lextractor.links_to_follow(self.atom)) self.assertEqual(len(links), 3) self.assertEqual(links[0].url, 'http://example.org/feed/') class TestXmlLinkExtractionFromSpider(TestCase): def setUp(self): smanager = SlybotSpiderManager("%s/data/SampleProject" % PATH) self.spider = smanager.create('books.toscrape.com_1') def test_xml_content(self): response = UTF8TextResponse( url='http://www.example.com/', body=xmlfeed, headers={'Content-Type': 'application/xml'}) links = list(self.spider.parse(response)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.wikipedia.org/') def test_endswith_xml(self): sitemap = UTF8TextResponse( url='http://www.example.com/sitemap.xml', body=sitemapfeed) sitemap_index = UTF8TextResponse( url='http://www.example.com/sitemap.xml', body=sitemapindex) links = list(self.spider.parse(sitemap)) self.assertEqual(len(links), 3) self.assertEqual(links[0].url, 'http://www.accommodationforstudents.com/') links = list(self.spider.parse(sitemap_index)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.example.com/sitemap1.xml.gz') def test_atom(self): atom = UTF8TextResponse( url='http://www.example.com/atom', body=atomfeed, headers={'Content-Type': 'application/atom+xml'}, encoding='utf-8') links = list(self.spider.parse(atom)) self.assertEqual(len(links), 3) self.assertEqual(links[0].url, 'http://example.org/feed/') def test_xml_response(self): xmlresponse = UTF8XmlResponse(url='http://example.com/', body=xmlfeed) links = list(self.spider.parse(xmlresponse)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.wikipedia.org/') csvfeed = """ My feed Product A,http://www.example.com/path,A Product B,http://www.example.com/path2,B """ csvfeed2 = """ My feed Product A|http://www.example.com/path|A Product B|http://www.example.com/path2|B """ csvfeed3 = """ My feed name,url,id Product A,http://www.example.com/path,A Product B,http://www.example.com/path2,B """ class Test_CsvLinkExtractor(TestCase): def test_simple(self): specs = {"type": "column", "value": 1} lextractor = create_linkextractor_from_specs(specs) response = UTF8TextResponse(url='http://www.example.com/', body=csvfeed) links = list(lextractor.links_to_follow(response)) self.assertEqual(len(links), 2) self.assertEqual(links[0].url, 'http://www.example.com/path') self.assertEqual(links[1].url, 'http://www.example.com/path2') def test_extra_params(self): specs = {"type": "column", "value": 1, "delimiter": "|"} lextractor = create_linkextractor_from_specs(specs) response = UTF8TextResponse(url='http://www.example.com/', body=csvfeed2) links = list(lextractor.links_to_follow(response)) self.assertEqual(len(links), 2) self.assertEqual(links[0].url, 'http://www.example.com/path') self.assertEqual(links[1].url, 'http://www.example.com/path2') def test_header(self): specs = {"type": "column", "value": 1} lextractor = create_linkextractor_from_specs(specs) response = UTF8TextResponse(url='http://www.example.com/', body=csvfeed3) links = list(lextractor.links_to_follow(response)) self.assertEqual(len(links), 2) self.assertEqual(links[0].url, 'http://www.example.com/path') self.assertEqual(links[1].url, 'http://www.example.com/path2') html = """ Click here """ _PATH = dirname(__file__) with open('%s/data/templates/daft_list.json' % _PATH) as f: daft_sample = json.load(f) daft_body = Annotations(daft_sample).apply() daft_sample['annotated_body'] = daft_body class Test_HtmlLinkExtractor(TestCase): def test_simple(self): specs = {"type": "html", "value": None} lextractor = create_linkextractor_from_specs(specs) response = UTF8HtmlResponse(url='http://www.example.com/', body=html) links = list(lextractor.links_to_follow(response)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.example.com/path') self.assertEqual(links[0].text, 'Click here') class Test_PaginationExtractor(TestCase): def test_simple(self): specs = {"type": "pagination", "value": None} lextractor = create_linkextractor_from_specs(specs) html_page = htmlpage_from_response( UTF8HtmlResponse(url='http://www.example.com/', body=html)) html_page.headers['n_items'] = 1 links = list(lextractor.links_to_follow(html_page)) self.assertEqual(len(links), 1) self.assertEqual(links[0].url, 'http://www.example.com/path') self.assertEqual(links[0].text, 'Click here') def test_start_urls(self): specs = { "type": "pagination", "value": None, "start_urls": ['http://www.spam.com/?p=1', 'http://www.eggs.com/?page=0'] } lextractor = create_linkextractor_from_specs(specs) html = """ Click here 1 Click here 2 Click here 3 """ html_page = htmlpage_from_response( UTF8HtmlResponse(url='http://www.example.com/', body=html)) links = list(lextractor.links_to_follow(html_page)) links = sorted(links, key=lambda link: link.url) self.assertEqual(len(links), 3) self.assertEqual(links[0].url, "http://www.spam.com/?p=100") self.assertEqual(links[1].url, "http://www.spam.com/?p=200") self.assertEqual(links[2].url, "http://www.spam.com/?p=300") self.assertEqual(links[0].text, 'Click here 1') self.assertEqual(links[1].text, 'Click here 2') self.assertEqual(links[2].text, 'Click here 3') def test_trained(self): base = 'http://www.daft.ie/ireland/houses-for-sale/?offset={}'.format daft_url = base(10) spec = { 'start_urls': [daft_url], 'links_to_follow': 'auto', 'respect_nofollow': False, 'follow_patterns': [], 'exclude_patterns': [], 'init_requests': [], 'templates': [daft_sample] } settings = Settings() settings.set('LOADED_PLUGINS', load_plugins(settings)) spider = IblSpider('hn', spec, {}, {}, settings=settings) request = Request(daft_url) response = UTF8HtmlResponse(url=daft_url, body=daft_body, request=request) data = {r.url for r in spider.handle_html(response) if isinstance(r, Request)} self.assertEqual({base(i) for i in (90, 80, 70)}, data) ================================================ FILE: slybot/slybot/tests/test_migration.py ================================================ import unittest from slybot.plugins.scrapely_annotations.migration import handle_tables class MigrationTests(unittest.TestCase): def test_table_generalization(self): selectors = [ ('table.mainbg > tr:nth-child(5) > td:nth-child(1) > ' 'table:nth-child(2) > tr:nth-child(3) > td:nth-child(1) > ' 'p:nth-child(1) > strong:nth-child(1)', 'table.mainbg > tr:nth-child(5) > td:nth-child(1) > ' 'table:nth-child(2) > tr:nth-child(3) > td:nth-child(1) > ' 'p:nth-child(1) > strong:nth-child(1), table.mainbg > * > ' 'tr:nth-child(5) > td:nth-child(1) > table:nth-child(2) > ' 'tr:nth-child(3) > td:nth-child(1) > p:nth-child(1) > ' 'strong:nth-child(1), table.mainbg > tr:nth-child(5) > ' 'td:nth-child(1) > table:nth-child(2) > * > tr:nth-child(3) > ' 'td:nth-child(1) > p:nth-child(1) > strong:nth-child(1), ' 'table.mainbg > * > tr:nth-child(5) > td:nth-child(1) > ' 'table:nth-child(2) > * > tr:nth-child(3) > td:nth-child(1) > ' 'p:nth-child(1) > strong:nth-child(1)'), ('div > p > .table > div > span', 'div > p > .table > div > span'), ('div > p > #table > div > span', 'div > p > #table > div > span'), ('div > p > table > div > span', 'div > p > table > div > span, div > p > table > * > div > span'), ('div > p > table:nth-child(4) > div > span', 'div > p > table:nth-child(4) > div > span, ' 'div > p > table:nth-child(4) > * > div > span'), ('table', 'table') ] for selector, generalized in selectors: self.assertEqual(handle_tables(selector), generalized) ================================================ FILE: slybot/slybot/tests/test_multiple_item_extraction.py ================================================ # -*- coding: utf-8 -*- import json import re from unittest import TestCase from scrapy import Request, Item from scrapy.settings import Settings from scrapy.http.response.html import HtmlResponse from slybot.plugins.scrapely_annotations.extraction import ( TemplatePageMultiItemExtractor, SlybotIBLExtractor) from slybot.plugins.scrapely_annotations.extraction.pageparsing import ( parse_template) from slybot.plugins.scrapely_annotations.extraction.container_extractors import ( BaseContainerExtractor, ContainerExtractor, RepeatedContainerExtractor) from slybot.plugins.scrapely_annotations.extraction.utils import group_tree from slybot.extractors import add_extractors_to_descriptors from slybot.item import create_slybot_item_descriptor from slybot.plugins.scrapely_annotations.builder import ( Annotations, _clean_annotation_data ) from slybot.spider import IblSpider from slybot.spidermanager import SlybotSpiderManager from scrapely.extraction.pageobjects import TokenDict from scrapely.htmlpage import HtmlPage from scrapely.extraction.regionextract import BasicTypeExtractor from scrapely.extraction.pageparsing import parse_extraction_page from scrapely.htmlpage import HtmlTagType from .utils import (open_spec, open_sample_and_page, open_page, make_spider, PATH, open_spider_page_and_results) base_page = u"""
      {}
    """.format item_template = u"""
  • {rank}

    Item i

    Text {idx} Text {idx}

    Text {idx} Text {idx}

  • """.format html = base_page('\n'.join(item_template(idx=i, rank=i if i % 2 else '') for i in range(1, 11))) annotations = _clean_annotation_data([{ 'id': 'annotation1', 'selector': 'li > div > h3 > a', 'container_id': 'repeated_parent', 'data': {1: {'attribute': 'content', 'field': 'title', 'required': False, 'extractors': []}, 2: {'attribute': 'href', 'field': 'url', 'required': False, 'extractors': ['1', '2']}}}, {'id': 'annotation2', 'selector': 'li > div > span', 'container_id': 'repeated_parent', 'data': {1: {'attribute': 'content', 'field': 'rank', 'required': True, 'extractors': []}}}, {'id': 'annotation3', 'selector': 'li > div:nth-child(2)', 'container_id': 'repeated_parent', 'data': {1: {'attribute': 'content', 'field': 'description', 'required': True, 'extractors': []}}}, {'id': 'parent', 'item_container': True, 'selector': 'ul'}, {'id': 'repeated_parent', 'item_container': True, 'container_id': 'parent', 'selector': 'li', 'repeated': True}]) schemas = { '#default': {'name': 'default_item', 'fields': {}}, 'data': { 'name': 'data_item', 'fields': { 'title': {'required': False, 'vary': False, 'type': 'text'}, 'url': {'required': False, 'vary': False, 'type': 'url'}, 'description': {'required': False, 'vary': False, 'type': 'text'}, 'rank': {'required': False, 'vary': False, 'type': 'price'}} } } sample = {'plugins': {'annotations-plugin': {'extracts': annotations}}, 'original_body': html} simple_template = HtmlPage(url="http://www.test.com/a", body=Annotations(sample).apply()) target1 = base_page('\n'.join(item_template(idx=i, rank=1) for i in range(1, 11))) target2 = base_page('\n'.join(item_template(idx=i, rank=i if i % 2 else '') for i in range(1, 11))) target1 = HtmlPage(url="http://www.test.com/a", body=target1) target2 = HtmlPage(url="http://www.test.com/a", body=target2) simple_descriptors = {k: create_slybot_item_descriptor(v) for k, v in schemas.items()} add_extractors_to_descriptors(simple_descriptors, {}) td = TokenDict() html_page = HtmlPage(body=open_spec('stack_overflow.html')) extraction_page = parse_extraction_page(td, html_page) with open('%s/data/SampleProject/items.json' % PATH) as f: items = json.load(f) descriptors = {'#default': create_slybot_item_descriptor(items['default'], 'default')} template = parse_template(td, html_page, descriptors) unvalidated_template = parse_template(td, html_page, {}) unvalidated_template.id = u'stack_overflow_test' basic_extractors = BasicTypeExtractor.create(template.annotations) uncontained_annotation = basic_extractors[0] root_container = basic_extractors[1] child_container = basic_extractors[2] child_annotations = basic_extractors[3:] sample_411, page_411 = open_sample_and_page('411_list.json') xceed_spider = open_spec('xceed.json') def _annotation_tag_to_dict(tag): return {attr: getattr(tag, attr, object()) for attr in ['annotation_text', 'end_index', 'metadata', 'start_index', 'surrounds_attribute', 'tag_attributes', 'variant_id']} class ContainerExtractorTest(TestCase): def test_get_container_info(self): containers, annotations, remaining_annotations = \ BaseContainerExtractor._get_container_data(basic_extractors) self.assertEqual(remaining_annotations, [uncontained_annotation]) self.assertEqual(containers, {'root': root_container, 'child': child_container}) self.assertEqual(annotations, {'child': child_annotations, 'root': [child_container]}) # TODO: test template with missing referenced container def test_build_extraction_tree(self): containers = {'root': root_container, 'child': child_container} tree = BaseContainerExtractor._build_extraction_tree(containers) self.assertEqual([['root'], ['root', 'child']], tree) # TODO: test cyclical tree def test_group_tree(self): annotations = {'child': child_annotations, 'root': [child_container]} tree1 = [['root']] self.assertEqual(group_tree(tree1, annotations), {'root': [child_container]}) tree2 = [['root'], ['root', 'child']] self.assertEqual(group_tree(tree2, annotations), {'root': {'child': child_annotations}}) def test_find_annotation(self): bce = BaseContainerExtractor(basic_extractors, template) a2d = _annotation_tag_to_dict self.assertEqual(a2d(bce._find_annotation(template, 'child')), a2d(child_container.annotation)) self.assertIsNone(bce._find_annotation(template, 'non_existant')) def test_validate_and_adapt_item(self): bce = BaseContainerExtractor(basic_extractors, template) data = {'price': ['10']} data['_type'] = 'skip_checks' result = bce._validate_and_adapt_item(data, template).dump() self.assertEqual(result, {'price': ['10'], '_type': 'skip_checks'}) data = { 'price': ['10'], u'description': [u'It can do everything except make calls'], u'name': ['Smartphone 6'] } result = data.copy() result['_type'] = 'default' extracted = bce._validate_and_adapt_item(data, template).dump() self.assertEqual(extracted, result) data['pid'] = ['13532'] result = data.copy() result['_type'] = 'default' extracted = bce._validate_and_adapt_item(data, template).dump() self.assertEqual(extracted, result) bce.extra_requires = ['pid', '_sticky1'] data['_sticky1'] = True extracted = bce._validate_and_adapt_item(data, template).dump() self.assertEqual(extracted, result) def test_find_tokens(self): htt = HtmlTagType s = RepeatedContainerExtractor._find_tokens(template.page_tokens[::-1], (htt.OPEN_TAG,), template) self.assertEqual(s, [16777216, 16777217, 16777218]) e = RepeatedContainerExtractor._find_tokens(template.page_tokens, (htt.CLOSE_TAG,), template) self.assertEqual(e, [33554432, 33554439, 33554438]) def test_extract(self): extractors = ContainerExtractor.apply(unvalidated_template, basic_extractors) ibl_extractor = TemplatePageMultiItemExtractor(unvalidated_template, extractors) data = [i.dump() for i in ibl_extractor.extract(extraction_page)] self.assertEqual(len(data), 96) self.assertEqual( {tuple(sorted(i.keys())) for i in data}, {(u'_index', u'_template', u'date', u'text', u'title', u'url')}) self.assertDictEqual(data[0], { u'_index': 1, u'_template': u'stack_overflow_test', u'date': [u'2015-08-07 10:09:32Z'], u'text': [u"Bootstrap navbar doesn't open - mobile view"], u'title': [u'I have a sticky nav with this code (Which is not mine' u')\n\n// Create a clone of the menu, right next to ' u'original.\n...'], u'url': [u'https://stackoverflow.com/questions/31875193/bootstrap-' u'navbar-doesnt-open-mobile-view'] }) self.assertDictEqual(data[50], { u'_index': 51, u'_template': u'stack_overflow_test', u'date': [u'2015-08-07 10:01:03Z'], u'text': [u'Rails in production with Apache+passenger error'], u'title': [u"Last days i'm trying to put my rails app in " u"production with apache and passenger(no rvm), but " u"still nothing. In my browser i get an error like " u"this:\n\nWe're sorry, but something went wrong." u"\nWe've been ..."], u'url': [u'https://stackoverflow.com/questions/31874997/rails-in-' u'production-with-apachepassenger-error'] }) self.assertDictEqual(data[-1], { u'_index': 96, u'_template': u'stack_overflow_test', u'date': [u'2015-08-07 08:16:43Z'], u'text': [u'iPython + Spark + Cassandra - Py4JJavaError and How to' u' connect to Cassandra from Spark?'], u'title': [u"How can I connect to Cassandra from Spark with " u"iPython?\n\nI have followed the code from here and " u"modified it,\n\nimport os\nimport sys\n\n# Path for " u"spark source folder\nos.environ['SPARK_HOME'] = ..."], u'url': [u'https://stackoverflow.com/questions/31872831/ipython-' u'spark-cassandra-py4jjavaerror-and-how-to-connect-to-' u'cassandra-from'] }) def test_extract_single_attribute_to_multiple_fields(self): extractors = {'1': {'regular_expression': '(.*)\s'}, '2': {'regular_expression': '\s(.*)'}} descriptors = {'#default': create_slybot_item_descriptor({'fields': { 'full_name': {'type': 'text', 'required': False, 'vary': False}, 'first_name': {'type': 'text', 'required': False, 'vary': False, 'name': u'prénom'}, 'last_name': {'type': 'text', 'required': False, 'vary': False, 'name': 'nom'}, 'address': {'type': 'text', 'required': False, 'vary': False}}})} add_extractors_to_descriptors(descriptors, extractors) extractor = SlybotIBLExtractor([(sample_411, descriptors, '0.13.0')]) data = extractor.extract(page_411)[0][1] self.assertEqual(data['full_name'], [u'Joe Smith']) self.assertEqual(data[u'prénom'], [u'Joe']) self.assertEqual(data['nom'], [u'Smith']) def test_extract_missing_schema(self): extractor = SlybotIBLExtractor([(sample_411, {}, '0.13.0')]) data = extractor.extract(page_411)[0][1] raw_html = ('Joe' ' Smith') self.assertEqual(data['full_name'], [raw_html]) self.assertEqual(data['first_name'], [raw_html]) self.assertEqual(data['last_name'], [raw_html]) def test_extract_multiple_item_types(self): spider = IblSpider('xceed', xceed_spider, xceed_spider['items'], {}, Settings()) data = list(spider.parse( HtmlResponse('http://url', body=xceed_spider['templates'][0]['original_body'], encoding='utf-8') )) items = sorted([d for d in data if not isinstance(d, Request)], key=lambda x: ('ticket', 'venue', 'event').index(x['_type'])) self.assertEqual(items, xceed_spider['results']) def test_extract_repeated_field(self): sample = { 'plugins': {'annotations-plugin': {}}, 'url': 'https://stackoverflow.com', 'original_body': re.sub( 'data-scrapy-annotate=".*"', '', html_page._body), 'scrapes': 'default', 'page_id': '507f520c3bf361f4c5cd55c44307a271bccb2218', 'version': '0.13.0' } data = open_spec('so_annotations.json') annos, items, results = data['annos'], data['items'], data['results'] sample['plugins']['annotations-plugin']['extracts'] = annos spider = IblSpider('so', make_spider(sample=sample), items, {}, Settings()) page = HtmlResponse('http://url', body=sample['original_body'], encoding='utf-8') items = [i for i in spider.parse(page) if not isinstance(i, Request)] keys = {(u'_index', u'_template', u'_type', u'answered', u'tags', u'title', 'url')} self.assertEqual({tuple(sorted(i.keys())) for i in items}, keys) self.assertEqual([items[0], items[52], items[-1]], results) self.assertEqual(len(items), 96) spider, page, results = open_spider_page_and_results('autoevolution.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, results) def test_item_merging_in_container(self): spider, page, results = open_spider_page_and_results('autoevolution2.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, results) def test_extracted_items_are_scrapy_items(self): spider, page, results = open_spider_page_and_results('autoevolution2.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertTrue(len(items) > 0) self.assertTrue(all(isinstance(i, Item) for i in items)) def test_required_annotation(self): ibl_extractor = SlybotIBLExtractor([ (simple_template, simple_descriptors, '0.13.0') ]) data, _ = ibl_extractor.extract(target1) self.assertEqual(len(data), 10) self.assertTrue(all('rank' in item and item['rank'] for item in data)) self.assertTrue(all('description' in item and item['description'] for item in data)) data, _ = ibl_extractor.extract(target2) self.assertEqual(len(data), 5) self.assertTrue(all('rank' in item and item['rank'] for item in data)) self.assertTrue(all('description' in item and item['description'] for item in data)) def test_missing_selectors(self): spider, page, results = open_spider_page_and_results('cars.com.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, results) def test_against_false_positive(self): page = open_page('autoevolution.html') spider, _, _ = open_spider_page_and_results('autoevolution2.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, []) def test_nested_items(self): smanager = SlybotSpiderManager("%s/data/SampleProject" % PATH) name = 'books.toscrape.com' spider = smanager.create(name) spec = smanager._specs["spiders"][name] t = [t for t in spec["templates"] if t['page_id'] == '3617-44af-a2f0'][0] response = HtmlResponse(t['url'], body=t['original_body'].encode('utf-8')) results = [i for i in spider.parse(response) if hasattr(i, '__getitem__')] self.assertEqual(results, t['results']) def test_nested_items_without_nested_structure(self): spider, page, results = open_spider_page_and_results( 'cars.com_nested.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, results) def test_empty_page(self): spider, page, _ = open_spider_page_and_results( 'cars.com_nested.json') page = HtmlResponse(page.url, body=u'', encoding='utf-8') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, []) def test_repeated_css_extractors(self): spider, page, results = open_spider_page_and_results('stips.co.il.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, results) spider, page, results = open_spider_page_and_results('firmen.wko.at.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, results) ================================================ FILE: slybot/slybot/tests/test_page_actions.py ================================================ from unittest import TestCase from slybot.pageactions import filter_for_url, PageActionsMiddleware from os.path import dirname from scrapy import Request from scrapy import Spider from slybot.spider import IblSpider _PATH = dirname(__file__) def mkreq(): return Request('http://localhost:9050', meta={ "splash": { "endpoint": "render.html", "args": { "url": "http://test.com", } } }) class PATest(TestCase): def test_url_filter(self): f = filter_for_url('http://test.com/path/foo/bar') self.assertTrue(f(dict(accept="\\/\\/test.com", reject="baz"))) self.assertTrue(f(dict(accept=None, reject="baz"))) self.assertTrue(f(dict(accept='foo/bar', reject=None))) self.assertFalse(f(dict(accept="//test.com", reject="foo/bar"))) self.assertFalse(f(dict(accept="foo", reject="bar"))) self.assertFalse(f(dict(accept=None, reject="foo/bar"))) self.assertFalse(f(dict(accept="baz", reject=None))) def test_middleware(self): m = PageActionsMiddleware() spider = Spider('test_spider') req = mkreq() spider.page_actions = [{ "type": "click", "selector": "#showmore" }] m.process_request(req, spider) self.assertEqual(req.meta['splash']['endpoint'], 'execute') # Page actions enabled req = mkreq() spider.page_actions = [] m.process_request(req, spider) self.assertEqual(req.meta['splash']['endpoint'], 'render.html') # Page actions disabled req = mkreq() spider.page_actions = [{ "type": "click", "selector": "#showmore", "reject": "test\\.com" }] m.process_request(req, spider) self.assertEqual(req.meta['splash']['endpoint'], 'render.html') # Page actions disabled ================================================ FILE: slybot/slybot/tests/test_schema_validation.py ================================================ # -*- coding: utf-8 -*- import re from unittest import TestCase from os.path import dirname, join from slybot.validation.schema import get_schema_validator, \ ValidationError, validate_project_schema from slybot.utils import open_project_from_dir _TEST_PROJECT_DIR = join(dirname(__file__), "data/SampleProject") def spider_json(start_urls): return { "start_urls": start_urls, "links_to_follow": "none", "respect_nofollow": True, "templates": [], } def start_url_schema(url_string): return {"url": url_string, "type": "url"} class JsonSchemaTest(TestCase): def test_regex_formatting_wrong(self): obj = { "0": { "regular_expression": "Item: (\d+" } } validator = get_schema_validator("extractors") with self.assertRaises(ValidationError): validator.validate(obj) def test_regex_formatting_ok(self): obj = { "0": { "regular_expression": "Item: (\d+)" } } validator = get_schema_validator("extractors") self.assertEqual(validator.validate(obj), None) def test_valid_url(self): legacy_start_urls = [ 'http://www.example.com/', 'http://www.example.com/經濟', 'http://www.example.com/?q=經濟', 'http://www.example.com/#經濟', 'http://faß.de', 'http://例.jp/', 'http://[2001:0000:1234:0000:0000:C1C0:ABCD:0876]/foo/bar', 'http://[2001::]/foo/bar', 'http://8.8.8.8/foo/bar', 'http://localhost:8080/foo/bar', 'http://foo@localhost:8080/foo/bar', 'http://foo:bar@localhost:8080/foo/bar', 'http://domain.com/path/file.html?param=FOO^111¶m2=bar¶m3=true&_param4=on', # Anonymized URL form sentry d46840d2457c4042b1b58f2fa40e984b 'https://domain.com/path/file.htm?param=foo#hash/foo/bar/baz:foo|bar:baz', # Anonymized URL from sentry 01dd2fa09d9540b69ebd33372b2b3a2d 'https://domain.com/path/file.htm?param=foo#hash/foo/bar/baz:foo|bar%5B%5D:12345', # Anonymized URL from sentry 87d49ee751494c90a8941dcbdacea634 'http://domain.com/path?bar[foo]=baz&foo[bar]=12345', # Anonymized URL from sentry 9f6835f5decd4d57b9475f04f0a58bd4 ] start_urls = list(map(start_url_schema, legacy_start_urls)) validator = get_schema_validator("spider") self.assertEqual(validator.validate(spider_json(legacy_start_urls)), None) self.assertEqual(validator.validate(spider_json(start_urls)), None) def test_invalid_url(self): legacy_start_urls = ( 12345, # Not a string 'example.com', # Lacks protocol 'http://[:::1]/foo/bar', # Bad IPv6 addr 'http://http://foo.com/bar', # Double protocol 'spotify:foobar', # Not http/s protocol '/foo', # relative '?foo', # relative '#foo', # relative ) validator = get_schema_validator("spider") for invalid_url in legacy_start_urls: with self.assertRaises(ValidationError): validator.validate(spider_json([invalid_url])) def test_valid_mixed_fragments(self): start_urls = [ {'type': 'url', 'url': 'http://www.example.com/'}, {'type': 'generated', 'url': 'http://', 'fragments': [ {'type': 'fixed', 'value': 'http://'} ]}, ] validator = get_schema_validator("spider") self.assertEqual(validator.validate(spider_json(start_urls)), None) def test_valid_fragments(self): fragments = ( [ {'type': 'fixed', 'value': 'domain.com'}, {'type': 'range', 'value': '0-10'} ], [{'type': 'range', 'value': '0-10'}], [{'type': 'list', 'value': 'a b c'}], [{'type': 'list', 'value': 'one_element'}] ) validator = get_schema_validator("spider") for fragment in fragments: start_url = [{ 'url': 'http://domain.com', 'type': 'generated', 'fragments': fragment }] self.assertEqual(validator.validate(spider_json(start_url)), None) def test_test_project(self): specs = open_project_from_dir(_TEST_PROJECT_DIR) self.assertTrue(validate_project_schema(specs)) ================================================ FILE: slybot/slybot/tests/test_selectors.py ================================================ from unittest import TestCase from scrapy.http import HtmlResponse, Request from slybot.spidermanager import SlybotSpiderManager from .utils import open_spider_page_and_results, PATH class SpiderTest(TestCase): smanager = SlybotSpiderManager("%s/data/SampleProject" % PATH) def test_spider_with_selectors(self): name = "seedsofchange" spider = self.smanager.create(name) spec = self.smanager._specs["spiders"][name] t = spec["templates"][1] response = HtmlResponse(t["url"], body=t["original_body"].encode('utf-8')) item = { '_template': u'4fac3b47688f920c7800000f', '_type': u'default', 'image': u'previous data', } spider.plugins['Selectors'].process_item(item, response) self.assertEqual(item['breadcrumbs'], [u'Seeds & Supplies', u'Seeds', u'Vegetables', u'Squash & Pumpkins']) self.assertEqual(item['image'], [u'previous data', u'/images/product_shots/PPS14165B.jpg']) def test_spider_with_inbuilt_selectors(self): """Test selectors for text, price, date and html extractors.""" name = 'books.toscrape.com' spider = self.smanager.create(name) spec = self.smanager._specs["spiders"][name] t = [t for t in spec["templates"] if t['page_id'] == "0a96a4dba3c62275ecf13903f42a007dd06718d8"][0] response = HtmlResponse(t['url'], body=t['original_body'].encode('utf-8')) results = [i for i in spider.parse(response) if hasattr(i, '__getitem__')] for result in results: result['posted'] = [result['posted'][0].strftime('%Y-%m-%d %H:%M')] self.assertEqual(results, t['_results']) def test_spider_with_surrounded_selectors(self): spider, page, results = open_spider_page_and_results('cs-cart.json') items = [i for i in spider.parse(page) if not isinstance(i, Request)] self.assertEqual(items, results) ================================================ FILE: slybot/slybot/tests/test_spider.py ================================================ from unittest import TestCase from os.path import dirname, join from contextlib import contextmanager from scrapy.http import Response, HtmlResponse, Request from scrapy.item import Item, DictItem from scrapy.utils.project import get_project_settings from scrapy.utils.reqser import request_to_dict from scrapely.htmlpage import HtmlPage from slybot.spidermanager import SlybotSpiderManager from .utils import UTF8HtmlResponse, UTF8TextResponse, UTF8XmlResponse _PATH = dirname(__file__) @contextmanager def splash_spider_manager(splash_url='http://localhost:8050'): settings = get_project_settings() settings.set('SPLASH_URL', splash_url) yield SlybotSpiderManager("%s/data/SampleProject" % _PATH, settings=settings) class SpiderTest(TestCase): smanager = SlybotSpiderManager("%s/data/SampleProject" % _PATH) def test_list(self): self.assertEqual(set(self.smanager.list()), set([ "seedsofchange", "seedsofchange2", "seedsofchange.com", "sitemaps", "pinterest.com", "ebay", "ebay2", "ebay3", "ebay4", "cargurus", "networkhealth.com", "allowed_domains", "any_allowed_domains", "example.com", "example2.com", "example3.com", "example4.com", "books.toscrape.com", "books.toscrape.com_1"])) def test_spider_with_link_template(self): name = "seedsofchange" spider = self.smanager.create(name) spec = self.smanager._specs["spiders"][name] t1, t2 = spec["templates"] target1, target2 = [HtmlPage(url=t["url"], body=t["original_body"]) for t in spec["templates"]] items, link_regions = spider.plugins['Annotations'].extract_items(target1) self.assertEqual(items, []) self.assertEqual(len(list(spider.plugins['Annotations']._process_link_regions(target1, link_regions))), 104) items, link_regions = spider.plugins['Annotations'].extract_items(target2) self.assertEqual(items[0], { '_template': u'4fac3b47688f920c7800000f', '_type': u'default', u'category': [u'Winter Squash'], u'days': [None], u'description': [u'1-2 lbs. (75-95 days) This early, extremely productive, compact bush variety is ideal for small gardens.  Miniature pumpkin-shaped fruits have pale red-orange skin and dry, sweet, dark orange flesh.  Great for stuffing, soups and pies.'], u'lifecycle': [u'Tender Annual'], u'name': [u'Gold Nugget'], u'price': [u'3.49'], u'product_id': [u'01593'], u'species': [u'Cucurbita maxima'], 'url': u'http://www.seedsofchange.com/garden_center/product_details.aspx?item_no=PS14165', u'weight': [None]} ) self.assertEqual(link_regions, []) self.assertEqual(len(list(spider.plugins['Annotations']._process_link_regions(target2, link_regions))), 0) def test_spider_with_link_region_but_not_link_template(self): name = "seedsofchange2" spider = self.smanager.create(name) spec = self.smanager._specs["spiders"][name] t1, t2 = spec["templates"] target1, target2 = [HtmlPage(url=t["url"], body=t["original_body"]) for t in spec["templates"]] items, link_regions = spider.plugins['Annotations'].extract_items(target2) self.assertEqual(items[0], { '_template': u'4fad6a7d688f922437000017', '_type': u'default', u'category': [u'Winter Squash'], u'days': [None], u'description': [u'1-2 lbs. (75-95 days) This early, extremely productive, compact bush variety is ideal for small gardens.  Miniature pumpkin-shaped fruits have pale red-orange skin and dry, sweet, dark orange flesh.  Great for stuffing, soups and pies.'], u'lifecycle': [u'Tender Annual'], u'name': [u'Gold Nugget'], u'price': [u'3.49'], u'species': [u'Cucurbita maxima'], 'url': u'http://www.seedsofchange.com/garden_center/product_details.aspx?item_no=PS14165', u'weight': [None]} ) self.assertEqual(len(link_regions), 1) self.assertEqual(len(list(spider.plugins['Annotations']._process_link_regions(target1, link_regions))), 25) def test_spider_extracted_item_types(self): name = "seedsofchange2" spider = self.smanager.create(name) spec = self.smanager._specs["spiders"][name] t1, t2 = spec["templates"] page = HtmlResponse(t1["url"], body=t2["original_body"], encoding='utf-8') items = [i for i in spider.parse(page) if not isinstance(i, Request)] print(items) print([type(item) for item in items]) self.assertIsInstance(items, list) self.assertIsInstance(items[0], Item) self.assertIsInstance(items[0], DictItem) def test_login_requests(self): name = "pinterest.com" spider = self.smanager.create(name) login_request = list(spider.start_requests())[0] response = UTF8HtmlResponse( url="https://pinterest.com/login/", body=open(join(_PATH, "data", "pinterest.html")).read()) response.request = login_request form_request = login_request.callback(response) expected = { '_class': 'scrapy.http.request.form.FormRequest', '_encoding': 'utf-8', 'body': b'email=test&password=testpass&csrfmiddlewaretoken=nLZy3NMzhTswZvweHJ4KVmq9UjzaZGn3&_ch=ecnwmar2', 'callback': 'after_login', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {b'Content-Type': [b'application/x-www-form-urlencoded']}, 'meta': {}, 'method': 'POST', 'priority': 0, 'url': u'https://pinterest.com/login/?next=%2F'} self.assertEqual(request_to_dict(form_request, spider), expected) # simulate a simple response to login post from which extract a link response = UTF8HtmlResponse( url="http://pinterest.com/", body="" "") result = list(spider.after_login(response)) self.assertEqual([r.url for r in result], [ 'http://pinterest.com/categories', 'http://pinterest.com/popular/' ]) def test_generic_form_requests(self): name = "ebay" spider = self.smanager.create(name) generic_form_request = list(spider.start_requests())[0] response = UTF8HtmlResponse( url="http://www.ebay.com/sch/ebayadvsearch/?rt=nc", body=open(join(_PATH, "data", "ebay_advanced_search.html")).read()) response.request = generic_form_request request_list = [{k: v for k, v in request_to_dict(req, spider).items() if not k.startswith('_')} for req in generic_form_request.callback(response)] expected = [{ 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=1&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=2&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=3&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=4&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50') }, { 'body': b'', 'callback': 'parse', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc'}] self.assertEqual(request_list, expected) def test_generic_form_requests_with_file_field(self): name = "ebay2" spider = self.smanager.create(name) generic_form_request = list(spider.start_requests())[0] self.assertEqual(generic_form_request.url, 'file://tmp/test_params.txt') response = UTF8HtmlResponse( url='file://tmp/test_params.txt', body=open(join(_PATH, "data", "test_params.txt")).read()) response.request = generic_form_request requests = list(generic_form_request.callback(response)) request_list = [request_to_dict(req, spider) for req in requests] expected = [{ 'body': b'', '_class': 'scrapy.http.request.form.FormRequest', '_encoding': 'utf-8', 'cookies': {}, 'flags': [], 'meta': { u'xpath': u"//form[@name='adv_search_from']", u'form_url': u'http://www.ebay.com/sch/ebayadvsearch/?rt=nc', u'type': u'form', 'field_index': 1, u'fields': [{ u'xpath': u".//*[@name='_nkw']", 'file_values': ['Cars', 'Boats'], u'type': u'inurl', u'value': u'file://tmp/test_params.txt' }, { u'type': u'inurl', u'name': u'_nkw2', u'value': u'file://tmp/test_params.txt' }, { u'xpath': u".//*[@name='_in_kw']", u'type': u'iterate' }] }, 'headers': {}, 'url': u'file://tmp/test_params.txt', 'dont_filter': True, 'priority': 0, 'callback': 'parse_field_url_page', 'method': 'GET', 'errback': None }] self.assertEqual(request_list, expected) generic_form_request = requests[0] self.assertEqual(generic_form_request.url, 'file://tmp/test_params.txt') response = UTF8HtmlResponse( url='file://tmp/test_params.txt', body=open(join(_PATH, "data", "test_params.txt")).read()) response.request = generic_form_request requests = list(generic_form_request.callback(response)) request_list = [request_to_dict(req, spider) for req in requests] expected = [{ '_encoding': 'utf-8', 'cookies': {}, 'flags': [], 'dont_filter': True, 'errback': None, 'meta': { 'fields': [{ 'type': 'inurl', 'file_values': ['Cars', 'Boats'], 'xpath': ".//*[@name='_nkw']", 'value': 'file://tmp/test_params.txt' }, { 'name': '_nkw2', 'file_values': ['Cars', 'Boats'], 'type': 'inurl', 'value': 'file://tmp/test_params.txt' }, { 'xpath': ".//*[@name='_in_kw']", 'type': 'iterate' }], 'type': 'form', 'xpath': "//form[@name='adv_search_from']", 'field_index': 1 }, 'method': 'GET', 'priority': 0, 'headers': {}, 'body': b'', 'url': 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc', 'callback': 'parse_form_page' }] self.assertEqual(request_list, expected) generic_form_request = requests[0] self.assertEqual(generic_form_request.url, 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc') response = UTF8HtmlResponse( url="http://www.ebay.com/sch/ebayadvsearch/?rt=nc", body=open(join(_PATH, "data", "ebay_advanced_search.html")).read()) response.request = generic_form_request request_list = [{k: v for k, v in request_to_dict(req, spider).items() if not k.startswith('_')} for req in generic_form_request.callback(response)] expected = [{ 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=1&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50&_nkw2=Cars') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=2&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50&_nkw2=Cars') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=3&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50&_nkw2=Cars') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=4&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50&_nkw2=Cars') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=1&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50&_nkw2=Boats') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=2&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50&_nkw2=Boats') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=3&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50&_nkw2=Boats') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=4&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50&_nkw2=Boats') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Boats&_in_kw=1&_ex_kw' '=&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_' 'ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsr' 'adio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_d' 'md=1&_ipg=50&_nkw2=Cars') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Boats&_in_kw=2&_ex_kw' '=&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_' 'ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsr' 'adio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_d' 'md=1&_ipg=50&_nkw2=Cars') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Boats&_in_kw=3&_ex_kw' '=&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_' 'ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsr' 'adio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_d' 'md=1&_ipg=50&_nkw2=Cars') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Boats&_in_kw=4&_ex_kw' '=&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_' 'ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsr' 'adio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_d' 'md=1&_ipg=50&_nkw2=Cars') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Boats&_in_kw=1&_ex_kw' '=&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_' 'ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsr' 'adio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_d' 'md=1&_ipg=50&_nkw2=Boats') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Boats&_in_kw=2&_ex_kw' '=&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_' 'ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsr' 'adio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_d' 'md=1&_ipg=50&_nkw2=Boats') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Boats&_in_kw=3&_ex_kw' '=&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_' 'ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsr' 'adio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_d' 'md=1&_ipg=50&_nkw2=Boats') }, { 'body': b'', 'callback': 'after_form_page', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': ('http://www.ebay.com/sch/i.html?_nkw=Boats&_in_kw=4&_ex_kw' '=&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_' 'ftrv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsr' 'adio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_d' 'md=1&_ipg=50&_nkw2=Boats') }, { 'body': b'', 'callback': 'parse', 'cookies': {}, 'dont_filter': True, 'errback': None, 'flags': [], 'headers': {}, 'meta': {}, 'method': 'GET', 'priority': 0, 'url': 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc'}] self.assertEqual(request_list, expected) def test_generic_form_requests_with_spider_args(self): name = "ebay3" args = {'search_string': 'Cars'} spider = self.smanager.create(name, **args) generic_form_request = list(spider.start_requests())[0] response = UTF8HtmlResponse( url="http://www.ebay.com/sch/ebayadvsearch/?rt=nc", body=open(join(_PATH, "data", "ebay_advanced_search.html")).read()) response.request = generic_form_request request_list = [request_to_dict(req, spider) for req in generic_form_request.callback(response)] expected = [{ 'body': b'', 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=1&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50'), 'dont_filter': True, 'priority': 0, 'meta': {}, 'cookies': {}, 'callback': 'after_form_page', 'flags': [], 'method': 'GET', '_encoding': 'utf-8', '_class': 'scrapy.http.request.form.FormRequest', 'headers': {}, 'errback': None }, { 'body': b'', 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=2&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50'), 'dont_filter': True, 'priority': 0, 'meta': {}, 'cookies': {}, 'callback': 'after_form_page', 'flags': [], 'method': 'GET', '_encoding': 'utf-8', '_class': 'scrapy.http.request.form.FormRequest', 'headers': {}, 'errback': None }, { 'body': b'', 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=3&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50'), 'dont_filter': True, 'priority': 0, 'meta': {}, 'cookies': {}, 'callback': 'after_form_page', 'flags': [], 'method': 'GET', '_encoding': 'utf-8', '_class': 'scrapy.http.request.form.FormRequest', 'headers': {}, 'errback': None }, { 'body': b'', 'url': ('http://www.ebay.com/sch/i.html?_nkw=Cars&_in_kw=4&_ex_kw=' '&_sacat=0&_okw=&_oexkw=&_adv=1&_udlo=&_udhi=&_ftrt=901&_f' 'trv=1&_sabdlo=&_sabdhi=&_samilow=&_samihi=&_salic=1&_fsra' 'dio=%26LH_SpecificSeller%3D1&_saslop=1&_sasl=&_sop=12&_dm' 'd=1&_ipg=50'), 'dont_filter': True, 'priority': 0, 'meta': {}, 'cookies': {}, 'callback': 'after_form_page', 'flags': [], 'method': 'GET', '_encoding': 'utf-8', '_class': 'scrapy.http.request.form.FormRequest', 'headers': {}, 'errback': None }, { 'body': b'', 'url': 'http://www.ebay.com/sch/ebayadvsearch/?rt=nc', 'dont_filter': True, 'priority': 0, 'meta': {}, 'cookies': {}, 'callback': 'parse', 'flags': [], 'method': 'GET', '_encoding': 'utf-8', 'headers': {}, 'errback': None }] self.assertEqual(request_list, expected) def test_allowed_domains(self): name = "allowed_domains" spider = self.smanager.create(name) expected = ['www.ebay.com', 'www.yahoo.com'] self.assertEqual(spider.allowed_domains, expected) def test_allowed_domains_all(self): name = "any_allowed_domains" spider = self.smanager.create(name) expected = None self.assertEqual(spider.allowed_domains, expected) def test_allowed_domains_previous_behavior(self): name = "cargurus" spider = self.smanager.create(name) expected = ['www.cargurus.com'] self.assertEqual(spider.allowed_domains, expected) def test_links_from_rss(self): body = open(join(_PATH, "data", "rss_sample.xml")).read() response = UTF8XmlResponse( url="http://example.com/sample.xml", body=body, headers={'Content-Type': 'application/rss+xml;charset=ISO-8859-1'}) name = "cargurus" spider = self.smanager.create(name) urls = [r.url for r in spider.parse(response)] self.assertEqual(len(urls), 3) self.assertEqual(set(urls), set([ "http://www.cargurus.com/Cars/2004-Alfa-Romeo-GT-Reviews-c10012", "http://www.cargurus.com/Cars/2005-Alfa-Romeo-GT-Reviews-c10013", "http://www.cargurus.com/Cars/2007-Alfa-Romeo-GT-Reviews-c10015"])) def test_links_from_atom(self): body = open(join(_PATH, "data", "atom_sample.xml")).read() response = UTF8XmlResponse( url="http://example.com/sample.xml", body=body, headers={'Content-Type': "application/atom+xml; charset=UTF-8"}) name = "sitemaps" spider = self.smanager.create(name) urls = [r.url for r in spider.parse(response)] self.assertEqual(len(urls), 3) self.assertEqual(set(urls), set([ "http://www.webupd8.org/sitemap.xml?page=1", "http://www.webupd8.org/sitemap.xml?page=2", "http://www.webupd8.org/sitemap.xml?page=3"])) def test_links_from_sitemap(self): body = open(join(_PATH, "data", "sitemap_sample.xml")).read() response = UTF8XmlResponse( url="http://example.com/sample.xml", body=body, headers={'Content-Type': "text/xml; charset=UTF-8"}) name = "sitemaps" spider = self.smanager.create(name) urls = [r.url for r in spider.parse(response)] self.assertEqual(len(urls), 3) self.assertEqual(set(urls), set([ "https://www.siliconrepublic.com/post-sitemap1.xml", "https://www.siliconrepublic.com/post-sitemap2.xml", "https://www.siliconrepublic.com/post-sitemap3.xml"])) def test_empty_content_type(self): name = "ebay4" spider = self.smanager.create(name) generic_form_request = list(spider.start_requests())[0] body = open(join(_PATH, "data", "ebay_advanced_search.html"), "rb").read() response = Response( url="http://www.ebay.com/sch/ebayadvsearch/?rt=nc", body=body) response.request = generic_form_request # must not raise an error for result in spider.parse(response): pass def test_variants(self): """Ensure variants are extracted as list of dicts""" name = "networkhealth.com" spider = self.smanager.create(name) spec = self.smanager._specs["spiders"][name] template, = spec["templates"] target = HtmlPage(url=template["url"], body=template["original_body"]) items, _ = spider.plugins['Annotations'].extract_items(target) for item in items: for variant in item["variants"]: self.assertEqual(type(variant), dict) def test_start_requests(self): name = "example.com" spider = self.smanager.create(name) start_requests = list(spider.start_requests()) self.assertEqual(len(start_requests), 2) self.assertEqual(start_requests[0].url, 'http://www.example.com/products.csv') self.assertEqual(start_requests[1].url, 'http://www.example.com/index.html') csv = """ My feed name,url,id Product A,http://www.example.com/path,A Product B,http://www.example.com/path2,B""" response = UTF8TextResponse(url="http://www.example.com/products.csv", body=csv) requests = list(start_requests[0].callback(spider, response)) self.assertEqual(len(requests), 2) self.assertEqual(requests[0].url, 'http://www.example.com/path') self.assertEqual(requests[1].url, 'http://www.example.com/path2') def test_start_requests_allowed_domains(self): name = "example2.com" spider = self.smanager.create(name) self.assertEqual(spider.allowed_domains, ['www.example.com']) def test_override_start_urls(self): name = "example2.com" spider = self.smanager.create(name, start_urls=['http://www.example.com/override.html']) start_requests = list(spider.start_requests()) self.assertEqual(start_requests[1].url, 'http://www.example.com/override.html') def test_generate_start_urls(self): spider = self.smanager.create("example4.com") self.assertEqual([ "http://www.example.com/about_us", "http://www.example.com/contact", "http://www.example.com/p/2", "http://www.example.com/p/3", "http://www.example.com/p/4" ], [r.url for r in spider._start_requests]) def test_links_to_follow(self): html = ("Link" "") response = UTF8HtmlResponse(url='http://www.example.com/index.html', body=html) name = "example3.com" spider = self.smanager.create(name, links_to_follow='none') start_requests = list(spider.start_requests()) requests = list(start_requests[0].callback(response)) self.assertEqual(len(requests), 0) def test_js_enable_patterns(self): with splash_spider_manager() as manager: spider = manager.create("example3.com", js_enabled=True, js_enable_patterns=['/products/']) product_url = 'http://www.example.com/products/1234' aboutus_url = 'http://www.example.com/aboutus' request = spider._add_splash_meta(Request(product_url)) self.assertEqual(request.meta['splash']['args']['url'], product_url) request = spider._add_splash_meta(Request(aboutus_url)) self.assertEqual(request.meta.get('splash'), None) def test_js_disable_patterns(self): with splash_spider_manager() as manager: spider = manager.create("example3.com", js_enabled=True, js_disable_patterns=['/products/']) product_url = 'http://www.example.com/products/1234' aboutus_url = 'http://www.example.com/aboutus' request = spider._add_splash_meta(Request(product_url)) self.assertEqual(request.meta.get('splash'), None) request = spider._add_splash_meta(Request(aboutus_url)) self.assertEqual(request.meta['splash']['args']['url'], aboutus_url) def test_js_enable_and_disable_patterns(self): with splash_spider_manager() as manager: spider = manager.create("example3.com", js_enabled=True, js_enable_patterns=['/products/'], js_disable_patterns=['/products/[a-zA-Z]']) product_list_url = 'http://www.example.com/products/cameras' product_url = 'http://www.example.com/products/1234' request = spider._add_splash_meta(Request(product_list_url)) self.assertEqual(request.meta.get('splash'), None) request = spider._add_splash_meta(Request(product_url)) self.assertEqual(request.meta['splash']['args']['url'], product_url) ================================================ FILE: slybot/slybot/tests/test_starturls.py ================================================ from unittest import TestCase from scrapy import Request from scrapy.http.response.text import TextResponse from slybot.starturls import ( FragmentGenerator, IdentityGenerator, StartUrlCollection, UrlGenerator, FeedGenerator) class StartUrlCollectionTest(TestCase): def setUp(self): self.generators = { 'start_urls': IdentityGenerator(), 'generated_urls': UrlGenerator(), 'url': IdentityGenerator(), 'generated': FragmentGenerator(), } def test_mixed_start_urls_generation(self): start_urls = [ 'http://google.com', {"type": "url", "url": "http://domain.com"}, { 'type': 'generated', 'url': 'https://github.com/[0-2]', 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, {'type': 'range', 'value': '0-2'}, ] } ] generated_start_urls = [ 'http://google.com', 'http://domain.com', 'https://github.com/0', 'https://github.com/1', 'https://github.com/2', ] generated = StartUrlCollection(start_urls, self.generators) self.assertEqual(list(generated), generated_start_urls) def test_generated_type(self): generated_start_urls = [ 'https://github.com/scrapinghub', 'https://github.com/scrapy', 'https://github.com/scrapy-plugins', ] start_urls = [ { "template": "https://github.com/{}", "paths": [{ "type": "options", "values": ["scrapinghub", "scrapy", "scrapy-plugins"], }], "params": [], "params_template": {} }, ] generated = StartUrlCollection(start_urls, self.generators) self.assertEqual(list(generated), generated_start_urls) def test_malformed_generated_type(self): expected_format = [ {'fragments': [{'type': 'fixed', 'value': 'https://github.com/'}, {'type': 'list', 'value': 'scrapinghub scrapy scrapy-plugins'}], 'type': 'generated', 'url': 'https://github.com/[...]/'}] start_urls = [ { "template": "https://github.com/{}/{}/{}", "paths": [{ "type": "options", "values": ["scrapinghub", "scrapy", "scrapy-plugins"], }], "params": [], "params_template": {} }, ] normalized = StartUrlCollection(start_urls, self.generators).normalize() self.assertEqual(normalized, expected_format) def test_unique_legacy_urls(self): start_urls = [ 'http://google.com', 'http://github.com', 'http://github.com', 'http://scrapinghub.com', 'http://scrapinghub.com', ] unique_urls = [ 'http://google.com', 'http://github.com', 'http://scrapinghub.com', ] self.assertEqual(StartUrlCollection(start_urls).uniq(), unique_urls) def test_unique_list_start_urls(self): start_urls = [ {"type": "url", "url": "http://domain.com"}, { 'type': 'generated', 'url': 'https://github.com/[...]', 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, {'type': 'list', 'value': 'scrapely portia'}, ] }, { 'type': 'generated', 'url': 'https://github.com/[...]', 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, {'type': 'list', 'value': 'scrapely scrapinghub portia'}, ] }, ] self.assertEqual(StartUrlCollection(start_urls).uniq(), start_urls) def test_allowed_domains_with_many_fragments(self): start_urls = [ { 'type': 'generated', 'url': 'https://github.com/[...]', 'fragments': [ {'type': 'fixed', 'value': 'https://github.com'}, {'type': 'list', 'value': '/a /b /c'}, {'type': 'range', 'value': '1-10000000'}, ] }, ] allowed_domains = [ 'https://github.com/a', 'https://github.com/b', 'https://github.com/c', ] collection_domains = StartUrlCollection(start_urls, self.generators).allowed_domains self.assertEqual(set(collection_domains), set(allowed_domains)) def test_allowed_domains_with_mixed_urls(self): start_urls = [ { 'type': 'generated', 'url': 'https://scrapinghub.com/[...]', 'fragments': [ {'type': 'fixed', 'value': 'https://scrapinghub.com/'}, {'type': 'range', 'value': '1-10000000'}, ] }, { 'type': 'generated', 'url': 'https://github[1-3].com/[...]', 'fragments': [ {'type': 'fixed', 'value': 'https://github'}, {'type': 'range', 'value': '1-3'}, {'type': 'fixed', 'value': '.com/'}, {'type': 'range', 'value': '1-10000000'}, ] }, {"type": "url", "url": "http://domain.com"}, 'http://google.com', ] allowed_domains = [ 'https://scrapinghub.com/', 'https://github1.com/', 'https://github2.com/', 'https://github3.com/', 'http://domain.com', 'http://google.com', ] collection_domains = StartUrlCollection(start_urls, self.generators).allowed_domains self.assertEqual(set(collection_domains), set(allowed_domains)) def test_empty_allowed_domains(self): start_urls = [ { 'type': 'generated', 'url': 'https://', 'fragments': [ {'type': 'fixed', 'value': 'https://'}, ] }, ] collection_domains = StartUrlCollection(start_urls, self.generators).allowed_domains self.assertEqual(collection_domains, []) def test_multiple_empty_allowed_domains(self): start_urls = [ { 'type': 'generated', 'url': 'https://', 'fragments': [ {'type': 'fixed', 'value': 'https://'}, {'type': 'fixed', 'value': 'scrapy'}, ] }, ] collection_domains = StartUrlCollection(start_urls, self.generators).allowed_domains self.assertEqual(collection_domains, []) def test_normalize_string_url(self): legacy = ['https://github.com/scrapinghub'] normalized = [{ 'url': 'https://github.com/scrapinghub', 'type': 'url', }] collection = StartUrlCollection(legacy, self.generators) self.assertEqual(legacy[0], normalized[0]['url']) self.assertEqual(list(collection.normalize()), normalized) def test_normalize_start_url(self): start_urls = [{ 'url': 'https://github.com/scrapinghub', 'type': 'fixed', }] collection = StartUrlCollection(start_urls, self.generators) self.assertEqual(list(collection.normalize()), start_urls) def test_normalize_generated_options(self): legacy = [{ "template": "https://github.com/{}", "paths": [{ "type": "options", "values": ["scrapinghub", "scrapy", "scrapy-plugins"], }], "params": [], "params_template": {} }] normalized = [{ 'url': 'https://github.com/[...]', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, { 'type': 'list', 'value': 'scrapinghub scrapy scrapy-plugins', }, ] }] collection = StartUrlCollection(legacy, self.generators) self.assertEqual(generator_set(UrlGenerator, legacy[0]), generator_set(FragmentGenerator, normalized[0])) self.assertEqual(list(collection.normalize()), normalized) def test_normalize_generated_default(self): legacy = [{ "template": "https://github.com/{}/fixed", "paths": [{ "type": "default", "values": ["scrapinghub", "scrapy", "scrapy-plugins"], }], "params": [], "params_template": {} }] normalized = [{ 'url': 'https://github.com/scrapinghub/fixed', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, { 'type': 'fixed', 'value': 'scrapinghub', }, {'type': 'fixed', 'value': '/fixed'}, ] }] collection = StartUrlCollection(legacy, self.generators) self.assertEqual(generator_set(UrlGenerator, legacy[0]), generator_set(FragmentGenerator, normalized[0])) self.assertEqual(list(collection.normalize()), normalized) def test_normalize_generated_dates(self): legacy = [{ "template": "http://www.commitstrip.com/{}/{}/{}", "paths": [{ "type": "default", "values": ["en"] }, { "type": "date", "values": ["%Y"], }, { "type": "date", "values": ["%m"] }], "params": [], "params_template": {} }] normalized = [{ 'url': 'http://www.commitstrip.com/en/[...]/[...]', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'http://www.commitstrip.com/'}, {'type': 'fixed', 'value': 'en'}, {'type': 'fixed', 'value': '/'}, {'type': 'date', 'value': '%Y'}, {'type': 'fixed', 'value': '/'}, {'type': 'date', 'value': '%m'}, ] }] collection = StartUrlCollection(legacy, self.generators) self.assertEqual(generator_set(UrlGenerator, legacy[0]), generator_set(FragmentGenerator, normalized[0])) self.assertEqual(list(collection.normalize()), normalized) def test_normalized_generated_range(self): legacy = [{ "template": "https://www.donedeal.ie/{}/{}/{}", "paths": [{ "type": "default", "values": ["cars-for-sale"] }, { "type": "options", "values": ["i"], }, { "type": "range", "values": [10, 20] }], "params": [], "params_template": {} }] normalized = [{ 'url': 'https://www.donedeal.ie/cars-for-sale/[...]/10-19', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'https://www.donedeal.ie/'}, {'type': 'fixed', 'value': 'cars-for-sale'}, {'type': 'fixed', 'value': '/'}, {'type': 'list', 'value': 'i'}, {'type': 'fixed', 'value': '/'}, {'type': 'range', 'value': '10-19'}, ] }] collection = StartUrlCollection(legacy, self.generators) self.assertEqual(generator_set(UrlGenerator, legacy[0]), generator_set(FragmentGenerator, normalized[0])) self.assertEqual(list(collection.normalize()), normalized) def test_normalized_generated_params_range(self): legacy = [{ "template": "http://www.smbc-comics.com/{}", "paths": [{ "type": "default", "values": ["index.php"] }], "params": [{ "name": "p", "type": "range", "values": [20, 31] }, { "name": "q", "type": "options", "values": ['comic'] }], "params_template": {} }] normalized = [{ 'url': 'http://www.smbc-comics.com/index.php?p=20-30&q=[...]', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'http://www.smbc-comics.com/'}, {'type': 'fixed', 'value': 'index.php'}, {'type': 'fixed', 'value': '?p='}, {'type': 'range', 'value': '20-30'}, {'type': 'fixed', 'value': '&q='}, {'type': 'list', 'value': 'comic'}, ] }] collection = StartUrlCollection(legacy, self.generators) self.assertEqual(generator_set(UrlGenerator, legacy[0]), generator_set(FragmentGenerator, normalized[0])) self.assertEqual(list(collection.normalize()), normalized) def test_normalized_generated_template_params(self): legacy = [{ "template": "https://encrypted.google.com/search", "paths": [], "params": [{ "name": "q", "type": "options", "values": ["nosetests", "tox"] }, { "name": "location", "type": "options", "values": ["dublin", "cork"] }], "params_template": [ ("hl", "en"), ("q", "python unittest") ] }] normalized = [{ 'url': 'https://encrypted.google.com/search?hl=en&q=[...]&location=[...]', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'https://encrypted.google.com/search'}, {'type': 'fixed', 'value': '?hl='}, {'type': 'fixed', 'value': 'en'}, {'type': 'fixed', 'value': '&q='}, {'type': 'list', 'value': 'nosetests tox'}, {'type': 'fixed', 'value': '&location='}, {'type': 'list', 'value': 'dublin cork'}, ] }] collection = StartUrlCollection(legacy, self.generators) self.assertEqual(generator_set(UrlGenerator, legacy[0]), generator_set(FragmentGenerator, normalized[0])) self.assertEqual(list(collection.normalize()), normalized) def test_normalized_mixed(self): legacy = [ { "template": "http://www.smbc-comics.com/{}", "paths": [{ "type": "default", "values": ["index.php"] }], "params": [{ "name": "p", "type": "range", "values": [20, 31] }, { "name": "q", "type": "options", "values": ['comic'] }], "params_template": {} }, 'http://github.com/scrapinghub.com', { 'url': 'https://github.com/[...]', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, { 'type': 'list', 'value': 'scrapinghub scrapy scrapy-plugins', }, ] } ] normalized = [ { 'url': 'http://www.smbc-comics.com/index.php?p=20-30&q=[...]', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'http://www.smbc-comics.com/'}, {'type': 'fixed', 'value': 'index.php'}, {'type': 'fixed', 'value': '?p='}, {'type': 'range', 'value': '20-30'}, {'type': 'fixed', 'value': '&q='}, {'type': 'list', 'value': 'comic'}, ] }, {'url': 'http://github.com/scrapinghub.com', 'type': 'url'}, { 'url': 'https://github.com/[...]', 'type': 'generated', 'fragments': [ {'type': 'fixed', 'value': 'https://github.com/'}, { 'type': 'list', 'value': 'scrapinghub scrapy scrapy-plugins', }, ] }, ] collection = StartUrlCollection(legacy, self.generators) self.assertEqual(list(collection.normalize()), normalized) def test_feed_url(self): url = 'http://example.com/feed' feed = FeedGenerator(lambda: 0) response = TextResponse(url, body=( 'http://example.com/1\r' 'http://example.com/2\r\n' 'http://example.com/3\n\r' 'http://example.com/4\n'), encoding='utf-8') self.assertEqual([r.url for r in feed.parse_urls(response)], [ 'http://example.com/1', 'http://example.com/2', 'http://example.com/3', 'http://example.com/4', ]) def generator_set(generator, start_urls): return set(list(generator()(start_urls))) ================================================ FILE: slybot/slybot/tests/test_starturls_generator.py ================================================ from datetime import datetime from unittest import TestCase from scrapy.settings import Settings from slybot.starturls import IdentityGenerator, UrlGenerator from slybot.validation.schema import get_schema_validator class StartUrlGenerators(TestCase): github_start_urls = [ 'https://github.com/scrapinghub', 'https://github.com/scrapy', 'https://github.com/scrapy-plugins' ] donedeal_start_urls = [ 'https://www.donedeal.ie/cars-for-sale/i/1', 'https://www.donedeal.ie/cars-for-sale/i/2', 'https://www.donedeal.ie/houses-for-sale/i/1', 'https://www.donedeal.ie/houses-for-sale/i/2', 'https://www.donedeal.ie/pets-for-sale/i/1', 'https://www.donedeal.ie/pets-for-sale/i/2', 'https://www.donedeal.ie/kitchens-for-sale/i/1', 'https://www.donedeal.ie/kitchens-for-sale/i/2' ] specs = { 'defaults': [{ "template": "https://github.com/{}", "paths": [{ "type": "default", "values": ["scrapinghub", "scrapy", "scrapy-plugins"], }], "params": [], "params_template": {} }], 'options': [{ "template": "https://github.com/{}", "paths": [{ "type": "options", "values": ["scrapinghub", "scrapy", "scrapy-plugins"], }], "params": [], "params_template": {} }], 'dates': [{ "template": "http://www.commitstrip.com/{}/{}/{}", "paths": [{ "type": "default", "values": ["en"] }, { "type": "date", "values": ["%Y"], }, { "type": "date", "values": ["%m"] }], "params": [], "params_template": {} }], 'range': [{ "template": "https://www.donedeal.ie/{}/{}/{}", "paths": [{ "type": "default", "values": ["cars-for-sale"] }, { "type": "options", "values": ["i"], }, { "type": "range", "values": [100000010, 100000000, -1] }], "params": [], "params_template": {} }], 'params_range': [{ "template": "http://www.smbc-comics.com/{}", "paths": [{ "type": "default", "values": ["index.php"] }], "params": [{ "name": "p", "type": "range", "values": [20, 30, 5] }, { "name": "q", "type": "options", "values": ['comic'] }], "params_template": {} }], 'spider_args': [{ "template": "https://www.donedeal.ie/{}/{}/{}", "paths": [{ "type": "spider_args", "values": ["categories", "sections"] }, { "type": "options", "values": ["i"], }, { "type": "range", "values": [1, 3] }], "params": [], "params_template": {} }], 'settings': [{ "template": "https://www.donedeal.ie/{}/{}/{}", "paths": [{ "type": "settings", "values": ["categories", "sections"] }, { "type": "options", "values": ["i"], }, { "type": "range", "values": [1, 3] }], "params": [], "params_template": {} }], 'params': [{ "template": "https://encrypted.google.com/search", "paths": [], "params": [{ "name": "q", "type": "options", "values": ["nosetests", "tox"] }, { "name": "location", "type": "options", "values": ["dublin", "cork"] }], "params_template": [ ("hl", "en"), ("q", "python unittest") ] }] } def test_schema_format(self): validator = get_schema_validator('spider') spider = { 'start_urls_type': 'generated_urls', 'start_urls': [], 'links_to_follow': 'none', 'respect_nofollow': True } for spec in self.specs.values(): spider['generated_urls'] = spec validator.validate(spider) def test_start_urls(self): self.assertEqual(self.github_start_urls, IdentityGenerator()(self.github_start_urls)) def test_generate_start_urls_from_defaults(self): genny = UrlGenerator() spec = self.specs['defaults'] self.assertEqual(["https://github.com/scrapinghub"], list(genny(spec[0]))) def test_generate_start_urls_from_options(self): genny = UrlGenerator() spec = self.specs['options'] self.assertEqual(self.github_start_urls, list(genny(spec[0]))) def test_generate_start_urls_from_date(self): now = datetime.now() genny = UrlGenerator() spec = self.specs['dates'] url = "http://www.commitstrip.com/en/{}/{:02}".format(now.year, now.month) self.assertEqual([url], list(genny(spec[0]))) def test_generate_start_urls_from_range(self): genny = UrlGenerator() spec = self.specs['range'] urls = ["https://www.donedeal.ie/cars-for-sale/i/%s" % i for i in range(100000010, 100000000, -1)] self.assertEqual(urls, list(genny(spec[0]))) def test_generate_start_urls_from_params_range(self): genny = UrlGenerator() spec = self.specs['params_range'] urls = ["http://www.smbc-comics.com/index.php?p=%s&q=comic" % i for i in range(20, 30, 5)] self.assertEqual(urls, list(genny(spec[0]))) def test_generate_start_urls_from_spider_arg(self): genny = UrlGenerator(spider_args={ 'categories': ['cars-for-sale', 'houses-for-sale'], 'sections': ['pets-for-sale', 'kitchens-for-sale'] }) spec = self.specs['spider_args'] self.assertEqual(self.donedeal_start_urls, list(genny(spec[0]))) def test_generate_start_urls_from_setting(self): genny = UrlGenerator(Settings(values={ 'categories': 'cars-for-sale,houses-for-sale', 'sections': ['pets-for-sale', 'kitchens-for-sale'] })) spec = self.specs['settings'] self.assertEqual(self.donedeal_start_urls, list(genny(spec[0]))) def test_generate_start_urls_from_params(self): genny = UrlGenerator() spec = self.specs['params'] base = "https://encrypted.google.com/search?hl=en&q=%s&location=%s" n, t, d, c = "nosetests", "tox", "dublin", "cork" arg = [(n, d), (n, c), (t, d), (t, c)] self.assertEqual([base % (q, l) for q, l in arg], list(genny(spec[0]))) def test_misconfigured_start_urls_spec_type(self): genny = UrlGenerator() spec = [{ "template": "http://www.smbc-comics.com/{}", "paths": [{ "type": "defaults", "values": ["index.php"] }], "params": [], "params_template": {} }] self.assertEqual([], list(genny(spec[0]))) def test_missing_arg_for_start_urls_spec(self): genny = UrlGenerator(Settings(values={'home': 'home.php'}), { 'index': 'index.php' }) spec = [{ "template": "http://www.smbc-comics.com/{}", "paths": [{ "type": "spider_args", "values": ["home"] }], "params": [], "params_template": {} }] self.assertEqual([], list(genny(spec[0]))) spec = [{ "template": "http://www.smbc-comics.com/{}", "paths": [{ "type": "settings", "values": ["index"] }], "params": [], "params_template": {} }] self.assertEqual([], list(genny(spec[0]))) ================================================ FILE: slybot/slybot/tests/utils.py ================================================ import json import six from scrapy.settings import Settings from os.path import dirname from scrapy.http.response.html import HtmlResponse from scrapy.http.response.text import TextResponse from scrapy.http.response.xml import XmlResponse from scrapy.utils.spider import arg_to_iter from scrapely.htmlpage import HtmlPage from slybot.spider import IblSpider from slybot.plugins.scrapely_annotations.builder import Annotations from slybot.utils import read PATH = dirname(__file__) def request_to_set(requests): return [(set(t[0]),) + t[1:] for t in requests] class UTF8Response(TextResponse): def __init__(self, *args, **kwargs): body = kwargs.get('body', args[3] if len(args) >= 4 else b'') if 'encoding' not in kwargs and isinstance(body, six.text_type): kwargs['encoding'] = 'utf-8' super(UTF8Response, self).__init__(*args, **kwargs) class UTF8HtmlResponse(UTF8Response, HtmlResponse): pass class UTF8TextResponse(UTF8Response, TextResponse): pass class UTF8XmlResponse(UTF8Response, XmlResponse): pass def make_spider(start_urls=None, sample=None): sample = [] if sample is None else arg_to_iter(sample) start_urls = [] if start_urls is None else arg_to_iter(start_urls) return {'start_urls': start_urls, 'templates': sample} def open_spec(name): use_json = True if name.endswith('.json') else False with open('%s/data/templates/%s' % (PATH, name)) as f: return json.load(f) if use_json else read(f) def open_sample_and_page(name): sample_spec = open_spec(name) url = sample_spec['url'] return (HtmlPage(url=url, body=Annotations(sample_spec).apply()), HtmlPage(url=url, body=sample_spec['original_body'])) def open_page(name): return HtmlResponse(url=name, body=open_spec(name), encoding='utf-8') def open_spider_page_and_results(name): sample_spec = open_spec(name) schemas = sample_spec['schemas'] results = sample_spec['results'] if 'original_body' not in sample_spec: sample_spec['original_body'] = open_spec( '{}.html'.format(name[:-len('.json')])) page = UTF8HtmlResponse('http://url', body=sample_spec['original_body']) spider = IblSpider(name, make_spider(sample=sample_spec), schemas, {}, Settings()) return spider, page, results ================================================ FILE: slybot/slybot/utils.py ================================================ from six.moves.urllib_parse import urlparse import chardet import itertools import json import os import re import six import sys from collections import OrderedDict, namedtuple from io import open from itertools import chain from scrapely.htmlpage import HtmlPage, HtmlTagType from scrapy.utils.misc import load_object from w3lib.encoding import html_body_declared_encoding TAGID = u"data-tagid" GENERATEDTAGID = u"data-genid" OPEN_TAG = HtmlTagType.OPEN_TAG CLOSE_TAG = HtmlTagType.CLOSE_TAG UNPAIRED_TAG = HtmlTagType.UNPAIRED_TAG # Encodings: https://w3techs.com/technologies/overview/character_encoding/all ENCODINGS = ['UTF-8', 'ISO-8859-1', 'Windows-1251', 'Shift JIS', 'Windows-1252', 'GB2312', 'EUC-KR', 'EUC-JP', 'GBK', 'ISO-8859-2', 'Windows-1250', 'ISO-8859-15', 'Windows-1256', 'ISO-8859-9', 'Big5', 'Windows-1254', 'Windows-874'] MimeType = namedtuple('MimeType', ['type', 'maintype', 'subtype', 'params']) def content_type(response): full_content_type = decode(response.headers.get('Content-Type') or u'') type_ = full_content_type.split(';', 1) split = type_[0].split('/', 1) if len(split) < 2: maintype = type_ subtype = '' else: maintype, subtype = split # Parse params if needed return MimeType(full_content_type, maintype, subtype, []) def encode(html, default=None): if isinstance(html, six.binary_type): return html return _encode_or_decode_string(html, type(html).encode, default) def decode(html, default=None): if isinstance(html, six.text_type): return html return _encode_or_decode_string(html, type(html).decode, default) def _encode_or_decode_string(html, method, default): if not default: encoding = html_body_declared_encoding(html) if encoding: default = [encoding] else: default = [] elif isinstance(default, six.string_types): default = [default] for encoding in itertools.chain(default, ENCODINGS): try: return method(html, encoding) except (UnicodeDecodeError, UnicodeEncodeError, LookupError): pass except AttributeError: return html encoding = chardet.detect(html).get('encoding') return method(html, encoding) def iter_unique_scheme_hostname(urls): """Return an iterator of tuples (scheme, hostname) over the given urls, filtering dupes """ scheme_hostname = set() for x in urls: p = urlparse(x) scheme_hostname.add((p.scheme, p.hostname)) return list(scheme_hostname) def open_project_from_dir(project_dir): storage = Storage(project_dir) specs = {"spiders": SpiderLoader(storage)} for name in ['project', 'items', 'extractors']: try: specs[name] = storage.open('{}.json'.format(name)) except IOError: specs[name] = {} return specs def read(fp, encoding='utf-8'): content = fp.read() if hasattr(content, 'decode'): content = content.decode('utf-8') return content def _build_sample(sample, legacy=False): from slybot.plugins.scrapely_annotations.builder import Annotations Annotations(sample, legacy=legacy).build() sample['annotated'] = True return sample def htmlpage_from_response(response, _add_tagids=False): body = response.body_as_unicode() if _add_tagids: body = add_tagids(body) return HtmlPage(response.url, response.headers, body, encoding=response.encoding) def load_plugins(settings): if settings.get('LOADED_PLUGINS', None): return settings.get('LOADED_PLUGINS', None) plugins = settings['PLUGINS'] if plugins: return [load_object(p) if isinstance(p, str) else p for p in plugins] else: from slybot.plugins.scrapely_annotations import Annotations return [Annotations] def load_plugin_names(settings): """ Generate a unique name for a plugin based on the class name module name and path >>> settings = {'PLUGINS': ['a', 'b.c', 'a.c']} >>> load_plugin_names(settings) ['a', 'c', 'a.c'] """ seen = set() def generate_name(path, maxsplit=0, splits=None): if splits is None: splits = len(path.split('.')) - 1 name = '.'.join(path.split('.', splits - maxsplit)[-1].rsplit('.', maxsplit)) if name not in seen or maxsplit >= splits: seen.add(name) return name return generate_name(path, maxsplit + 1, splits) if settings['PLUGINS']: return [generate_name(path) for path in settings['PLUGINS']] else: return ['Annotations'] def include_exclude_filter(include_patterns, exclude_patterns): filterf = None includef = None if include_patterns: pattern = include_patterns[0] if len(include_patterns) == 1 else \ "(?:%s)" % '|'.join(include_patterns) includef = re.compile(pattern).search filterf = includef if exclude_patterns: pattern = exclude_patterns[0] if len(exclude_patterns) == 1 else \ "(?:%s)" % '|'.join(exclude_patterns) excludef = re.compile(pattern).search if not includef: filterf = lambda x: not excludef(x) else: filterf = lambda x: includef(x) and not excludef(x) return filterf if filterf else bool class IndexedDict(OrderedDict): """ Ordered dictionary where values can also be obtained by their index as if they were in a list >>> idd = IndexedDict([('spam', 1), ('eggs', 2), ('bacon', 3)]) >>> idd['spam'] 1 >>> idd[0] 1 >>> idd['bacon'] 3 >>> idd[2] 3 >>> idd[2] = 'ham' Traceback (most recent call last): ... TypeError: keys must not be an integers >>> idd[3] Traceback (most recent call last): ... IndexError: index out of range """ def __setitem__(self, key, value): if isinstance(key, int): raise TypeError("keys must not be an integers") super(IndexedDict, self).__setitem__(key, value) def __getitem__(self, key): if isinstance(key, int): if key >= len(self): raise IndexError('index out of range') for i, k in enumerate(self): if i == key: key = k break return super(IndexedDict, self).__getitem__(key) def _quotify(mystr): """ quotifies an html tag attribute value. Assumes then, that any ocurrence of ' or " in the string is escaped if original string was quoted with it. So this function does not altere the original string except for quotation at both ends, and is limited just to guess if string must be quoted with '"' or "'" """ quote = '"' length = len(mystr) for i in range(length): if mystr[i] == "\\" and i + 1 < length and mystr[i + 1] == "'": quote = "'" break elif mystr[i] == "\\" and i + 1 < length and mystr[i + 1] == '"': quote = '"' break elif mystr[i] == "'": quote = '"' break elif mystr[i] == '"': quote = "'" break return quote + mystr + quote def serialize_tag(tag): """ Converts a tag into a string when a slice [tag.start:tag.end] over the source can't be used because tag has been modified """ out = "<" if tag.tag_type == HtmlTagType.CLOSE_TAG: out += "/" out += tag.tag attributes = [] for key, val in tag.attributes.items(): aout = key if val is not None: aout += "=" + _quotify(val) attributes.append(aout) if attributes: out += " " + " ".join(attributes) if tag.tag_type == HtmlTagType.UNPAIRED_TAG: out += "/" return out + ">" def _must_add_tagid(element): return (hasattr(element, 'tag_type') and hasattr(element, 'tag') and element.tag_type != CLOSE_TAG and element.tag != 'ins') def _modify_tagids(source, add=True): """Add or remove tags ids to/from HTML document""" output = [] tagcount = 0 if not isinstance(source, HtmlPage): source = HtmlPage(body=source) for element in source.parsed_body: if _must_add_tagid(element): if add: element.attributes[TAGID] = str(tagcount) tagcount += 1 else: # Remove previously added tagid element.attributes.pop(TAGID, None) output.append(serialize_tag(element)) else: output.append(source.body[element.start:element.end]) return u''.join(output) def add_tagids(source): """ Applies a unique attribute code number for each tag element in order to be identified later in the process of apply annotation""" return _modify_tagids(source, True) def remove_tagids(source): """remove from the given page, all tagids previously added by add_tagids() """ return _modify_tagids(source, False) class Storage(object): def __init__(self, base_path): self.base_path = os.path.abspath(base_path) def rel_path(self, *args): return os.sep.join(args) def _path(self, *args): return os.path.join(self.base_path, self.rel_path(*args)) def isdir(self, *args, **kwargs): return os.path.isdir(self._path(*args), **kwargs) def listdir(self, *args, **kwargs): return os.listdir(self._path(*args), **kwargs) def open(self, *args, **kwargs): """Open files from filesystem.""" raw = kwargs.pop('raw', False) with open(self._path(*args), encoding='utf-8') as f: return decode(f.read()) if raw else json.load(f) class SpiderLoader(object): def __init__(self, storage): if isinstance(storage, six.string_types): self.storage = Storage(storage) else: fsattrs = ['isdir', 'listdir', 'open', 'rel_path'] if any(not hasattr(storage, attr) for attr in fsattrs): raise TypeError('Storage class must have "{}" methods'.format( '", "'.join(fsattrs))) self.storage = storage self.spider_dir = self.storage.rel_path('spiders') self.spider_names = { s[:-len('.json')] for s in self.storage.listdir(self.spider_dir) if s.endswith('.json') } self._spiders = {} def __getitem__(self, key): if key not in self.spider_names: raise KeyError('The spider "{}" does not exist'.format(key)) if key not in self._spiders: self._spiders[key] = self.load_spider(key) return self._spiders[key] def load_spider(self, spider_name): spec = self.storage.open(self.spider_dir, '{}.json'.format(spider_name)) try: if spec.get('templates'): templates = [] for template in spec.get('templates', []): if template.get('version', '') < '0.13.0': templates.append(template) else: templates.append(_build_sample(template)) spec['templates'] = templates else: templates = self.load_external_templates(self.spider_dir, spider_name) spec.setdefault("templates", []).extend(templates) return spec except ValueError as e: raise ValueError( "Error parsing spider (invalid JSON): %s: %s" % (spider_name, e) ) def keys(self): for spider_name in self.spider_names: yield spider_name def items(self): spiders = chain(self._spiders, self.spider_names - set(self._spiders)) for spider_name in spiders: yield spider_name, self[spider_name] def values(self): for _, spider in self.items(): yield spider def load_external_templates(self, spec_base, spider_name): """A generator yielding the content of all passed `template_names` for `spider_name`. """ spider_dir = self.storage.rel_path('spiders', spider_name) if not self.storage.isdir(spider_dir): if sys.version_info < (3, 6): raise StopIteration else: return for name in self.storage.listdir(spider_dir): if not name.endswith('.json'): continue path = self.storage.rel_path(spider_dir, name) sample = self.storage.open(path) if not sample: continue sample_dir = path[:-len('.json')] if self.storage.isdir(sample_dir): for fname in self.storage.listdir(sample_dir): if fname.endswith('.html'): attr = fname[:-len('.html')] html = self.storage.open(sample_dir, fname, raw=1) sample[attr] = html if 'original_body' not in sample: sample['original_body'] = u'' version = sample.get('version', '') yield _build_sample(sample, legacy=version < '0.13.0') ================================================ FILE: slybot/slybot/validation/__init__.py ================================================ ================================================ FILE: slybot/slybot/validation/schema.py ================================================ """Simple validation of specifications passed to slybot""" from __future__ import absolute_import from os.path import dirname, join import json import re import socket from six.moves.urllib.parse import ( urlsplit, urlunsplit ) from jsonschema import (Draft3Validator, RefResolver, FormatChecker, ValidationError) import six _PATH = dirname(__file__) def load_schemas(): filename = join(_PATH, "schemas.json") return dict((s["id"], s) for s in json.load(open(filename))) _SCHEMAS = load_schemas() class SlybotJsonSchemaValidator(Draft3Validator): DEFAULT_TYPES = Draft3Validator.DEFAULT_TYPES.copy() DEFAULT_TYPES.update({ "mapping": dict, }) def is_valid_ipv6_address(address): try: socket.inet_pton(socket.AF_INET6, address) except socket.error: # not a valid address return False return True def get_url_re(): """ Generate a URI validation regexp. Slightly modified from Django's URL validation https://github.com/django/django/blob/master/django/core/validators.py """ ul = '\u00a1-\uffff' # unicode letters range (must be a unicode string, not a raw string) # IP patterns ipv4_re = r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}' ipv6_re = r'\[[0-9a-f:\.]+\]' # Simple RE, validated later # Host patterns hostname_re = r'[a-z' + ul + r'0-9](?:[a-z' + ul + r'0-9-]{0,61}[a-z' + ul + r'0-9])?' # Max length for domain name labels is 63 characters per RFC 1034 sec. 3.1 domain_re = r'(?:\.(?!-)[a-z' + ul + r'0-9-]{1,63}(? ACE url = urlunsplit((scheme, netloc, path, query, fragment)) if not URL_RE.match(url): return False # Validate IPv6 ipv6_match = re.search(r'^\[(.+)\](?::\d{2,5})?$', netloc) if ipv6_match: potential_ip = ipv6_match.groups()[0] if not is_valid_ipv6_address(potential_ip): return False return True # Workaround for https://github.com/Julian/jsonschema/pull/272 @FormatChecker.cls_checks('regex', (Exception)) def is_valid_re(re_source): if not isinstance(re_source, six.string_types): return False if isinstance(re_source, six.binary_type): re_source = re_source.decode('utf-8') re.compile(re_source) return True return SlybotJsonSchemaValidator(_SCHEMAS[schema], resolver=resolver, format_checker=FormatChecker()) def validate_project_schema(specs): project = specs["project"] get_schema_validator("project").validate(project) items = specs["items"] get_schema_validator("items").validate(items) extractors = specs["extractors"] get_schema_validator("extractors").validate(extractors) spider_schema_validator = get_schema_validator("spider") for spider in specs["spiders"].values(): spider_schema_validator.validate(spider) return True ================================================ FILE: slybot/slybot/validation/schemas.json ================================================ [ { "id": "project", "type": "object", "properties": { "name": {"type": "string", "required": true}, "version": {"type": "string", "required": true}, "comment": {"type": "string"} } }, { "id": "items", "additionalProperties": { "$ref": "item" } }, { "id": "item", "type": "object", "properties": { "fields": {"additionalProperties": {"$ref": "field"}, "required": true}, "name": {"type": "string", "required": false} } }, { "id": "field", "type": "object", "properties": { "type": {"type": "string", "required": true}, "required": {"type": "boolean", "required": true}, "vary": {"type": "boolean", "required": true}, "name": {"type": "string", "required": false} } }, { "id": "extractors", "additionalProperties": {"$ref": "extractor"} }, { "id": "extractor", "type": "object", "properties": { "type_extractor": {"type": "string"}, "regular_expression": {"type": "string", "format": "regex"} } }, { "id": "spider", "type": "object", "properties": { "start_urls": { "type": "array", "items": {"type": [{"$ref": "fixed_url"}, {"$ref": "start_url"}]}, "required": true }, "links_to_follow": {"type": "string", "enum": ["none", "patterns", "all", "auto"], "required": true}, "follow_patterns": {"type": "array", "items": {"type": "string", "format": "regex"}}, "exclude_patterns": {"type": "array", "items": {"type": "string", "format": "regex"}}, "js_enabled": {"type": "boolean"}, "js_enable_patterns": {"type": "array", "items": {"type": "string", "format": "regex"}}, "js_disable_patterns": {"type": "array", "items": {"type": "string", "format": "regex"}}, "respect_nofollow": {"type": "boolean", "required": true}, "allowed_domains": {"type": ["array", "null"], "items": {"type": "string"}}, "templates": {"type": "array", "items": {"$ref": "template"}}, "page_actions": {"type": "array", "items": {"$ref": "action"}}, "init_requests": {"type": "array", "items": {"$ref": "request"}} } }, { "id": "fixed_url", "type": "string", "format": "url" }, { "id": "start_url", "type": "object", "properties": { "url": {"type": "string", "required": true}, "type": {"type": "string", "enum": ["url", "generated"], "required": true}, "fragments": {"type": "array", "items": {"$ref": "url_fragment"}} }, "additionalProperties": false }, { "id": "url_fragment", "type": "object", "properties": { "type": {"type": "string", "enum": ["fixed", "range", "list"], "required": true}, "value": {"type": "string", "required": true} } }, { "id": "generated_url", "type": "object", "properties": { "template": {"type": "string", "required": true}, "paths": {"type": "array", "items": {"$ref": "generated_path_url_component"}, "required": true}, "params": {"type": "array", "items": {"$ref": "generated_param_url_component"}, "required": true} } }, { "id": "generated_path_url_component", "type": "object", "properties": { "type": {"type": "string", "required": true}, "values": {"type": "array", "required": true} } }, { "id": "generated_param_url_component", "type": "object", "properties": { "type": {"type": "string", "required": true}, "values": {"type": "array", "required": true}, "name": {"type": "string", "required": true} } }, { "id": "template", "type": "object", "properties": { "page_id": {"type": "string", "required": true}, "page_type": {"type": "string", "enum": ["links", "item"], "required": true}, "scrapes": {"type": "string", "required": true}, "url": {"type": "string", "format": "url", "required": true}, "extractors": {"additionalProperties": {"type": "array", "items": {"type": "string"}}, "required": true}, "annotated_body": {"type": "string", "required": false}, "original_body": {"type": "string", "required": true}, "selectors": { "type": "object", "patternProperties": { "[a-zA-Z0-9_-]+": {"$ref": "selector"} } } } }, { "id": "selector", "type": "object", "properties": { "type": {"enum": ["xpath", "css"], "required": true}, "selector": {"type": "string", "required": true} } }, { "id": "link_extractor", "type": "object", "properties": { "type": {"type": "string", "required": true}, "value": {"type": "any", "required": true}, "additionalProperties": {"type": "any"} } }, { "id": "request", "type": "object", "properties": { "type": {"type": "string", "required": true}, "link_extractor": {"$ref": "link_extractor"}, "additionalProperties": {"type": "any"} } }, { "id": "action", "type": "object", "allOf": [{ "properties": { "accept": {"type": "string", "format": "regex"}, "reject": {"type": "string", "format": "regex"} } }, { "oneOf": [ { "properties": { "type": {"enum": ["wait"]}, "timeout": {"type": "number", "minimum": 0, "required": true} } }, { "properties": { "type": {"enum": ["click"]}, "selector": {"type": "string", "required": true} } }, { "properties": { "type": {"enum": ["scroll"]}, "selector": {"type": "string", "required": true}, "percent": {"type": "number", "minimum": 0, "maximum": 100, "required": true} } }, { "properties": { "type": {"enum": ["set"]}, "value": {"type": "string", "required": true}, "selector": {"type": "string", "required": true} } } ] }] } ] ================================================ FILE: slybot/tox.ini ================================================ # Tox (http://tox.testrun.org/) is a tool for running tests # in multiple virtualenvs. This configuration file will run the # test suite on all supported python versions. To use it, "pip install tox" # and then run "tox" from this directory. [tox] envlist = py27,py37 [testenv] deps = -r{toxinidir}/requirements-test.txt -r{toxinidir}/requirements.txt commands = nosetests \ --with-doctest \ --with-doctest-ignore-unicode \ --doctest-options='+IGNORE_UNICODE' ================================================ FILE: slyd/.gitignore ================================================ # python *.py[cod] # editor files *.orig *.bak *.swp *.project *.sublime-* # twisted dropin.cache twistd.log twistd.pid _trial_temp* # local data files data/* # npm files node_modules/* npm-debug.log ================================================ FILE: slyd/.jshintrc ================================================ { "predef": [ "document", "window", "$", "URI", "CanvasLoader", "TreeMirror", "Raven", "-Promise" ], "browser": true, "boss": false, "curly": true, "debug": false, "devel": true, "eqeqeq": true, "evil": true, "forin": false, "immed": false, "laxbreak": false, "newcap": true, "noarg": true, "noempty": false, "nonew": false, "nomen": false, "onevar": false, "plusplus": false, "regexp": false, "undef": true, "sub": true, "strict": false, "white": false, "eqnull": true, "esnext": true, "unused": true } ================================================ FILE: slyd/README.md ================================================ How to try it: -------------- The recommended way to install dependencies is to use virtualenv and then do: pip install -r requirements.txt Run the server using: twistd -n slyd and point your browser to: http://localhost:9001/static/index.html Chrome and Firefox are supported, but it works better with chrome. Slyd API Notes -------------- This will be moved to separate docs - it's currently some notes for developers All resources are either under /dist/ or /projects/. project listing/creation/deletion/renaming To get list all existing projects, just GET http://localhost:9001/projects: $ curl http://localhost:9001/projects -> ["project1", "project2"] New projects can be created by posting to /projects, for example: $ curl -d '{"cmd": "create", "args": ["project_X"]}' http://localhost:9001/projects To delete a project: $ curl -d '{"cmd": "rm", "args": ["project_X"]}' http://localhost:9001/projects To rename a project: $ curl -d '{"cmd": "mv", "args": ["oldname", "newname"]}' http://localhost:9001/projects Please note that projects will not be overwritten when renaming or creating new ones (if a project with the given name already exists an error from the 400 family will be returned). spec The project specification is available under /projects/PROJECT_ID/spec. The path format mirrors the slybot format documented here: http://slybot.readthedocs.org/en/latest/project.html Currently, this is read only, but it will soon support PUT/POST. The entire spec is returned for a GET request to the root: $ curl http://localhost:9001/projects/78/spec {"project": { "version": "1308771278", "name": "demo" .. } A list of available spiders can be retrieved: $ curl http://localhost:9001/projects/78/spec/spiders ["accommodationforstudents.com", "food.com", "pinterest.com", "pin", "mhvillage"] and specific resources can be requested: $ curl http://localhost:9001/projects/78/spec/spiders/accommodationforstudents.com { "templates": ... "respect_nofollow": true } The spec can be updating by POSTing: $ curl --data @newlinkedin.js http://localhost:9001/projects/78/spec/spiders/linkedin An HTTP 400 will be returned if the uploaded spec does not validate. Basic commands are available for manipulating spider files. For example: $ curl -d '{"cmd": "rm", "args": ["spidername"]}' http://localhost:9001/projects/78/spec/spiders Available commands are: * mv - move spider from first arg to second. If the second exists it is overwritten. * rm - delete spider bot/fetch Accepts json object with the following fields: * request - same as scrapy requst object. At least needs a url * spider - spider name within in the project * page_id - unique ID for this page, must match the id used in templates (not yet implemented) Returns a json object containing (so far): * page - page content, not yet annotated but will be * response - object containing the response data: http code and headers * items - array of items extracted * fp - request fingerprint * error - error message, present if there was an error * links - array of links followed Coming soon in the response: * template_id - id of template that matched * trace - textual trace of the matching process - for debugging If you want to work on an existing project, put it in data/projects/PROJECTID, these can be downloaded from dash or by: $ bin/sh2sly data/projects -p 78 -k YOURAPIKEY Then you can extract data: $ curl -d '{"request": {"url": "http://www.pinterest.com/pin/339740365610932893/"}, "spider": "pinterest.com"}' http://localhost:9001/projects/78/bot/fetch { "fp": "0f2686acdc6a71eeddc49045b7cea0b6f81e6b61", "items": [ { "url": "http://www.pinterest.com/pin/339740365610932893/", "_template": "527387aa4d6c7133c6551481", "image": [ "http://media-cache-ak0.pinimg.com/736x/6c/c5/35/6cc5352046df0f8d8852cbdfb31542bb.jpg" ], "_type": "pin", "name": [ "Career Driven" ] } ], "page": "\n ...." } Testing ------- slyd can be tested using twisted: trial tests ================================================ FILE: slyd/bin/init_mysql_db ================================================ #!/usr/bin/env python3 import os import sys try: import slyd import slyd.settings as settings_module from scrapy.settings import Settings settings = Settings() settings.setmodule(settings_module) os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings['DJANGO_SETTINGS']) except ImportError: sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) try: import slyd except ImportError: sys.stderr.write("Error: Can't find the project package 'slyd'.\n") sys.exit(1) from portia_server.storage.repoman import Repoman def main(): Repoman.setup( storage_backend='slyd.gitstorage.repo.MysqlRepo', location=os.environ.get('DB_URL'), ) Repoman.pool._runWithConnection(Repoman.init_backend) if __name__ == '__main__': main() ================================================ FILE: slyd/bin/sh2sly ================================================ #!/usr/bin/env python3 """ Downloads AS projects from scrapinghub in slybot format and saves them locally Used for testing. This uses the python-scrapinghub library """ def sh2sly(apikey, projects, destination): from scrapinghub import Connection, Project import tempfile, zipfile, os conn = Connection(apikey) if not projects: projects = conn.project_ids() #projects = xrange(1300) out = tempfile.TemporaryFile() for projectid in projects: project = Project(conn, projectid) project.autoscraping_project_slybot(outputfile=out) try: zf = zipfile.ZipFile(out) scount = len([f for f in zf.namelist() if f.startswith('spiders/')]) if scount == 0: print "skipping %s - no spiders" % projectid continue pdest = os.path.join(destination, str(projectid)) zf.extractall(pdest) print "extracted project with %d spiders to %s" % (scount, pdest) except zipfile.BadZipfile: print "error with zipfile in project %s, skipping" % projectid out.truncate() def main(): import argparse parser = argparse.ArgumentParser( description='fetch slybot projects from scrapinghub') parser.add_argument('-p', '--project', type=int, action='append', help='scrapinghub project, may be repeated, default is all') parser.add_argument('-k', '--apikey', help='api key') parser.add_argument('destination') args = parser.parse_args() sh2sly(args.apikey, args.project, args.destination) if __name__ == '__main__': main() ================================================ FILE: slyd/bin/slyd ================================================ #!/usr/bin/env python3 import splash.server import splash.defaults import argparse DEFAULT_PORTIA_PORT = 9001 DEFAULT_PORTIA_ROOT = '../portiaui/dist' splash.defaults.SPLASH_PORT = DEFAULT_PORTIA_PORT def parse_args(): op = argparse.ArgumentParser() op.add_argument('-p', '--port', default=DEFAULT_PORTIA_PORT, type=int) op.add_argument('-r', '--root', default=DEFAULT_PORTIA_ROOT, help='Location of Portia webserver assets') return op.parse_args() def make_server(*args, **kwargs): from slyd.tap import makeService from twisted.internet import reactor opts = parse_args() reactor.listenTCP(opts.port, makeService({'port': opts.port, 'docroot': opts.root})) if __name__ == '__main__': splash.server.main(server_factory=make_server, argv=[]) ================================================ FILE: slyd/requirements.txt ================================================ # Slyd requirements twisted==19.2.1 pyOpenSSL==17.5.0 service_identity==18.1.0 requests>=2.20.0 autobahn==18.3.1 six==1.12.0 chardet==3.0.4 parse==1.8.2 ndg-httpsclient==0.4.4 retrying==1.3.3 mock==2.0.0 # Splash dev https://github.com/scrapinghub/splash/archive/3.2.x.tar.gz ================================================ FILE: slyd/setup.py ================================================ from setuptools import setup, find_packages install_requires = ['Scrapy', 'scrapely', 'loginform', 'lxml', 'jsonschema', 'django', 'parse', 'marshmallow_jsonapi', 'chardet', 'autobahn', 'requests', 'service_identity', 'ndg-httpsclient'] tests_requires = install_requires setup(name='slyd', license='BSD', description='Portia', author='Scrapinghub', url='http://github.com/scrapinghub/portia', packages=find_packages(), platforms=['Any'], scripts=['bin/sh2sly', 'bin/slyd', 'bin/init_mysql_db'], classifiers=[ 'Development Status :: 4 - Beta', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7' ]) ================================================ FILE: slyd/slyd/__init__.py ================================================ ================================================ FILE: slyd/slyd/authmanager.py ================================================ from scrapy.utils.misc import load_object class AuthManager(object): def __init__(self, settings): self.settings = settings auth_settings = settings.get('AUTH_CONFIG', {}) self.auth_method = load_object( auth_settings.get('CALLABLE', 'slyd.dummyauth.protectResource')) self.config = auth_settings.get('CONFIG', {}) def protectResource(self, resource): return self.auth_method(resource, config=self.config) ================================================ FILE: slyd/slyd/dummyauth.py ================================================ from twisted.web.resource import Resource def protectResource(resource, config): '''Dummy resource protector.''' return DummyAuthResource(resource) class DummyAuthResource(Resource): """A wrapper that injects dummy auth info to every passing request.""" def __init__(self, resource): Resource.__init__(self) self.wrapped = resource def getChildWithDefault(self, path, request): request.auth_info = { 'username': 'defaultuser', } # Don't consume any segments. request.postpath.insert(0, request.prepath.pop()) return self.wrapped ================================================ FILE: slyd/slyd/errors.py ================================================ class BaseError(Exception): def __init__(self, status, title, body=''): self._status = status self._title = title self._body = body @property def title(self): return self._title @property def body(self): return self._body @property def status(self): return self._status def __repr__(self): return '%s(%s)' % (self.__class__.__name__, str(self)) def __str__(self): return '%s: %s' % (self.status, self.title) class BaseHTTPError(BaseError): _status = 999 def __init__(self, title, body=''): super(BaseHTTPError, self).__init__(self._status, title, body) class BadRequest(BaseHTTPError): _status = 400 ================================================ FILE: slyd/slyd/gitstorage/__init__.py ================================================ ================================================ FILE: slyd/slyd/gitstorage/jsondiff.py ================================================ import difflib from collections import namedtuple from six.moves import zip_longest _BLANK = object() class Conflict(object): def __init__(self, mine, other, base): self.mine = [mine] if mine is not _BLANK else None self.other = [other] if other is not _BLANK else None self.base = [base] if base is not _BLANK else None @classmethod def from_prepared(cls, mine, other, base): m = mine[0] if mine else _BLANK o = other[0] if other else _BLANK b = base[0] if base else _BLANK conflict = cls(m, o, b) for m, o, b in zip_longest(mine[1:], other[1:], base[1:], fillvalue=_BLANK): conflict.update(m, o, b) return conflict @classmethod def resolve_sub_conflict(cls, mine, other): c = cls.from_prepared(mine, other, []) return c.resolve_conflict() def update(self, m, o, b): if m is not _BLANK: self.mine.append(m) if o is not _BLANK: self.other.append(o) if b is not _BLANK: self.base.append(b) def resolve_conflict(self): if self.mine is None and self.other is not None: return self.other if self.other is None and self.mine is not None: return self.mine if self.other == self.mine: return self.mine combined = set(self.mine or []) | set(self.other or []) if (self.base is not None and not any(i in combined for i in self.base)): return [self] mine = self.mine if self.mine else [] other = self.other if self.other else [] i_mine, i_other = iter(mine), iter(other) result, new_mine, new_other = [], [], [] for diff in difflib.Differ().compare([str(i) for i in other], [str(i) for i in mine]): if ((diff.startswith('+') and (new_other or result)) or (diff.startswith('-') and (new_mine or result)) or (result and (new_other or new_mine))): if new_mine or new_other: result.insert(0, Conflict.from_prepared(new_mine, new_other, [])) result.extend(Conflict.resolve_sub_conflict( [i for i in i_mine], [i for i in i_other])) break elif diff.startswith('-'): new_other.append(next(i_other)) elif diff.startswith('+'): new_mine.append(next(i_mine)) elif diff.startswith(' '): next(i_other) result.append(next(i_mine)) return result def _asdict(self): return { 'my_op': 'CHANGED', 'my_val': self.mine, 'other_op': 'CHANGED', 'other_val': self.other, 'base_val': self.base } def __eq__(self, other): return (self.mine == other.mine and self.other == other.other and self.base == other.base) def __str__(self): return 'Conflict{}'.format(str((self.mine, self.other, self.base))) def __repr__(self): return str(self) def merge_lists(base, mine, other): if mine == other: return mine if other == base: return mine if mine == base: return other result = [] last_conflict = False for i, (m, o, b) in enumerate(zip_longest(mine, other, base, fillvalue=_BLANK)): if (m == o and _BLANK not in (m, o) or isinstance(m, dict) and isinstance(o, dict)): result.append(m) else: # Conflict if last_conflict: c = result[-1] c.update(m, o, b) else: c = Conflict(m, o, b) result.append(c) last_conflict = True continue last_conflict = False offset = 0 for i, r in enumerate(result[:]): if isinstance(r, Conflict): c = r.resolve_conflict() result = result[:i + offset] + c + result[i + offset + 1:] offset += len(c) - 1 return result class JsonDiff(object): """ Compares two json objects and stores the differences. Only the outermost objects are considered, the comparison does not recurse into nested objects. """ def __init__(self, old, new): set_new, set_old = set(new), set(old) common = set_new & set_old self.added = list(set_new - common) self.removed = list(set_old - common) self.changed = [k for k in common if new[k] != old[k]] self.unchanged = [k for k in common if new[k] == old[k]] def op_for_field(self, field_name): for operation in ('ADDED', 'UNCHANGED', 'CHANGED', 'REMOVED'): if field_name in getattr(self, operation.lower()): return operation return None FieldDiff = namedtuple( 'DiffOp', ['my_op', 'my_val', 'other_op', 'other_val', 'base_val']) def merge_jsons(base, mine, other): """ Performs a 3-way merge of mine and other using base as the common ancestor. Some conflicts are automatically resolved, e.g. mine and other both delete the same field. Conflicts that can't be automatically resolved (e.g. mine and other assign different values to the same field) are serialized into the merged json in a way that can be used for a later manual resolve: field: { __CONFLICT: base_val: X, # the original value of the field my_val: Y, # the value assigned by mine json my_op: Z, # the operation performed by mine json other_val: U, # the value assigned by other json other_op: W, # the operation performed by other json } my_op and other_op can take any of this values: 'ADDED', 'REMOVED', 'CHANGED', 'UNCHAGED'. If my_op == 'DELETED' then my_value == None (the same applies to other_op and other_val respectively). The merge recurses into dictionaries but considers lists as atomic values. Returns a tuple of the form (merged, had_conflict). """ def build_merge_dict(base, mine, other): my_diff = JsonDiff(base, mine) other_diff = JsonDiff(base, other) base, mine, other = (j if isinstance(j, dict) else {} for j in (base, mine, other)) all_fields = set(base.keys()).union(mine.keys()).union(other.keys()) merge_dict = {} for k in all_fields: base_val, my_val, other_val = ( base.get(k, {}), mine.get(k), other.get(k)) if isinstance(my_val, dict) and isinstance(other_val, dict): merge_dict[k] = build_merge_dict(base_val, my_val, other_val) if isinstance(my_val, list) and isinstance(other_val, list): merge_dict[k] = merge_lists(base_val, my_val, other_val) else: merge_dict[k] = FieldDiff(base_val=base.get(k), my_val=my_val, my_op=my_diff.op_for_field(k), other_val=other_val, other_op=other_diff.op_for_field(k)) return merge_dict def eq_vals(diff): return diff.other_val == diff.my_val def conflict(diff): return {'__CONFLICT': diff._asdict()} def resolve_json(merge_dict): out_json = {} had_conflict = False for key, diff in merge_dict.items(): if isinstance(diff, dict): out_json[key], rconflict = resolve_json(diff) had_conflict = had_conflict or rconflict if isinstance(diff, list): for i, item in enumerate(diff): if isinstance(item, Conflict): if (item.mine and isinstance(item.mine[0], dict) and '__CONFLICT' in item.mine[0]): diff[i] = item.mine[0] else: diff[i] = conflict(item) had_conflict = True out_json[key] = diff elif diff.my_op in ('UNCHANGED', None): if diff.other_op != 'REMOVED': out_json[key] = diff.other_val elif diff.my_op == 'ADDED': if diff.other_op != 'ADDED' or eq_vals(diff): out_json[key] = diff.my_val else: out_json[key] = conflict(diff) had_conflict = True elif diff.my_op == 'REMOVED': if diff.other_op == 'CHANGED': out_json[key] = conflict(diff) had_conflict = True elif diff.my_op == 'CHANGED': if diff.other_op == 'UNCHANGED' or eq_vals(diff): out_json[key] = diff.my_val else: out_json[key] = conflict(diff) had_conflict = True return out_json, had_conflict return resolve_json(build_merge_dict(base, mine, other)) ================================================ FILE: slyd/slyd/gitstorage/projects.py ================================================ import json import re from os.path import splitext, split, exists from dulwich.errors import ObjectMissing from slyd.projects import ProjectsManager from slyd.errors import BadRequest from storage.backends import ContentFile, GitStorage from storage.repoman import Repoman _SHA = re.compile('[a-f0-9]{7,40}') def wrap_callback(connection, callback, manager, retries=0, **parsed): result = callback(**parsed) manager.commit_changes() return result class GitProjectMixin(object): storage_class = GitStorage @classmethod def setup(cls, storage_backend, location): Repoman.setup(storage_backend) cls.base_dir = '' if exists(location): cls.base_dir = location def run(self, callback, **parsed): pool = getattr(Repoman, 'pool', None) if pool is None: return wrap_callback(None, callback, self, **parsed) return pool.runWithConnection(wrap_callback, callback, self, **parsed) def _project_name(self, name): if name is None: name = getattr(self, 'project_name') return name def _open_repo(self, name=None, read_only=False): if getattr(self, 'storage', None): return self.storage.repo branch, repo = self._get_branch_and_repo(None, read_only, name) self.storage = self.storage_class(repo, branch, commit=repo.last_commit, tree=repo.last_tree) return repo def _get_branch_and_repo(self, repo=None, read_only=False, name=None): if getattr(self, 'storage', None): return self.storage.branch, self.storage.repo if repo is None: repo = self._init_or_open_project(name) if repo.has_branch(self.user): return self.user, repo elif not read_only and self.user: repo.create_branch(self.user, repo.get_branch('master')) return self.user, repo else: return 'master', repo def _checkout_commit_or_head(self, name=None, commit_id=None, branch='master'): branch_name, repo = self._get_branch_and_repo( read_only=True, name=name) commit = None try: if commit_id: commit = repo._repo.get_object(commit_id) elif branch: branch_name = branch commit_id = repo.refs['refs/heads/%s' % branch_name] commit = repo._repo.get_object(commit_id) except (ValueError, ObjectMissing) as e: raise BadRequest(str(e)) except KeyError as e: raise BadRequest('Could not find ref: %s' % e) self.storage = self.storage_class(repo, branch_name, commit=commit) def _get_branch(self, repo=None, read_only=False, name=None): return self._get_branch_and_repo(repo, read_only, name)[0] def _init_or_open_project(self, name): name = self._project_name(name) if not Repoman.repo_exists(name, self.connection): pm = getattr(self, 'pm', self) pm.create_project(name) if getattr(pm, 'storage', None): self.storage = pm.storage return self.storage.repo return Repoman.open_repo(self._project_name(name), self.connection, self.user) def list_spiders(self, name=None): self._open_repo(self._project_name(name), read_only=True) _, files = self.storage.listdir('spiders') return [splitext(split(f)[1])[0] for f in files if f.endswith(".json")] class GitProjectsManager(GitProjectMixin, ProjectsManager): def __init__(self, *args, **kwargs): ProjectsManager.__init__(self, *args, **kwargs) self.project_commands = { 'create': self.create_project, 'mv': self.rename_project, 'rm': self.remove_project, 'edit': self.edit_project, 'publish': self.publish_project, 'discard': self.discard_changes, 'revisions': self.project_revisions, 'conflicts': self.conflicted_files, 'changes': self.changed_files, 'save': self.save_file, 'copy': self.copy_data, 'download': self.download_project, 'has_tag': self.has_tag } self.modify_request = { 'download': self._render_file } self.connection = None def all_projects(self): return [{'name': repo, 'id': repo} for repo in Repoman.list_repos(self.connection)] def create_project(self, name): self.validate_project_name(name) try: repo = Repoman.create_repo(name, self.connection, self.user) except NameError: raise BadRequest("Bad Request", 'A project already exists with the name "%s".' % name) self.storage = self.storage_class(repo, 'master', tree=repo.last_tree, commit=repo.last_commit) super(GitProjectsManager, self).create_project(name) def project_filename(self, name): return name def remove_project(self, name): Repoman.delete_repo(name, self.connection) def publish_project(self, name, force): repoman = self._open_repo(name) if (repoman.publish_branch(self._get_branch(repoman), force=force) == True): repoman.delete_branch(self._get_branch(repoman)) return {'status': 'ok'} else: return {'status': 'conflict'} def has_tag(self, name, tag_name): return json.dumps({'status': self._has_tag(name, tag_name)}) def _has_tag(self, name, tag_name): repo = self._open_repo(name) if ('refs/tags/%s' % tag_name) in repo._repo.refs: return True return False def discard_changes(self, name): repoman = self._open_repo(name) repoman.delete_branch(self._get_branch(repoman)) def project_revisions(self, name): repoman = self._open_repo(name) return json.dumps({'revisions': repoman.get_published_revisions()}) def conflicted_files(self, name): repoman = self._open_repo(name, read_only=True) branch = self._get_branch(repoman, read_only=True) conflicts = repoman.publish_branch(branch, dry_run=True) return json.dumps(conflicts if conflicts is not True else {}) def changed_files(self, name): return json.dumps([ fname or oldn for _, fname, oldn in self._changed_files(name) ]) def _changed_files(self, name): repoman = self._open_repo(name, read_only=True) branch = self._get_branch(repoman, read_only=True) changes = repoman.get_branch_changed_entries(branch) return [ (entry.type, entry.new.path, entry.old.path) for entry in changes ] def save_file(self, name, file_path, file_contents): self._open_repo(name) self.storage.save(file_path, ContentFile( json.dumps(file_contents, sort_keys=True, indent=4), file_path)) def _render_file(self, request, request_data, body): if len(body) == 0: request.setHeader('ETag', self._gen_etag(request_data)) request.setResponseCode(304) return '' try: error = json.loads(body) if error.get('status', 0) == 404: request.setResponseCode(404) request.setHeader('Content-Type', 'application/json') except (TypeError, ValueError): try: _id = request_data.get('args')[0] name = self._get_project_name(_id).encode('utf-8') except (TypeError, ValueError, IndexError): name = 'archive' request.setHeader('ETag', self._gen_etag(request_data)) request.setHeader('Content-Type', 'application/zip') request.setHeader('Content-Disposition', 'attachment; ' 'filename="%s.zip"' % name) request.setHeader('Content-Length', len(body)) return body def _get_project_name(self, _id): if 'project_data' in getattr(self.request, 'auth_info', {}): for project in self.request.auth_info['project_data']: if hasattr(project, 'get') and project.get('id') == _id: return project.get('name') or _id return _id def _gen_etag(self, request_data): args = request_data.get('args') last_commit = self.storage._commit.id spiders = args[1] if len(args) > 1 and args[1] else [] return (last_commit + '.' + '.'.join(spiders)).encode('utf-8') def _schedule_info(self, **kwargs): return {} ================================================ FILE: slyd/slyd/gitstorage/projectspec.py ================================================ from slyd.projectspec import ProjectSpec from slyd.gitstorage.projects import GitProjectMixin class GitProjectSpec(GitProjectMixin, ProjectSpec): def _schedule_data(self, spider, args): branch = args.pop('branch', [None])[0] commit = args.pop('commit_id', [None])[0] project = self.project_name arg = {} if commit: arg['commit'] = commit elif branch: arg['branch'] = branch if not arg and self.storage.repo.has_branch(self.user): arg['branch'] = self.user self._checkout_commit_or_head(project, **arg) commit_id = self.storage._commit.id return { 'project': self.project_name, 'version': commit_id, 'spider': spider } ================================================ FILE: slyd/slyd/html_utils.py ================================================ """ Removes JavaScript from HTML This module removes all existing JavaScript in an HTML document. """ from __future__ import absolute_import import re import six from six.moves.urllib_parse import urljoin from scrapely.htmlpage import HtmlTag, HtmlTagType, parse_html from slyd.splash.css_utils import process_css, wrap_url from slybot.utils import serialize_tag, add_tagids URI_ATTRIBUTES = ("action", "background", "cite", "classid", "codebase", "data", "href", "longdesc", "profile", "src", "usemap") BLOCKED_TAGNAMES = ('script', 'noscript', 'object', 'embed') _ALLOWED_CHARS_RE = re.compile('[^!-~]') # [!-~] = ascii printable characters def _contains_js(url): return _ALLOWED_CHARS_RE.sub('', url).lower().startswith('javascript:') try: from html import unescape except ImportError: # https://html.spec.whatwg.org/multipage/syntax.html#character-references # http://stackoverflow.com/questions/18689230/why-do-html-entity-names-with-dec-255-not-require-semicolon _ENTITY_RE = re.compile("&#(\d+|x[a-f\d]+);?", re.I) def _replace_entity(match): entity = match.group(1) if entity[0].lower() == 'x': return six.unichr(int(entity[1:], 16)) else: return six.unichr(int(entity, 10)) def unescape(mystr): """replaces all numeric html entities by its unicode equivalent. """ return _ENTITY_RE.sub(_replace_entity, mystr) def html4annotation(htmlpage, baseurl=None, proxy_resources=None): """Convert the given html document for the annotation UI This adds tags, removes scripts and optionally adds a base url """ htmlpage = add_tagids(htmlpage) cleaned_html = descriptify(htmlpage, baseurl, proxy=proxy_resources) return cleaned_html def descriptify(doc, base=None, proxy=None): """Clean JavaScript in a html source string. """ parsed = parse_html(doc) newdoc = [] inserted_comment = False for element in parsed: if isinstance(element, HtmlTag): if element.tag in BLOCKED_TAGNAMES: # Asumes there are no void elements in BLOCKED_TAGNAMES # http://www.w3.org/TR/html5/syntax.html#void-elements if not inserted_comment and element.tag_type in (HtmlTagType.OPEN_TAG, HtmlTagType.UNPAIRED_TAG): newdoc.append('<%s>' % element.tag) inserted_comment = True elif element.tag_type == HtmlTagType.CLOSE_TAG: newdoc.append('' % element.tag) inserted_comment = False elif element.tag == 'base': element.attributes = {} newdoc.append(serialize_tag(element)) else: for key, val in element.attributes.copy().items(): # Empty intrinsic events if key.startswith('on') or key == "http-equiv": element.attributes[key] = "" elif base and proxy and key == "style" and val is not None: element.attributes[key] = process_css(val, -1, base) elif element.tag in ('frame', 'iframe') and key == 'src': element.attributes[key] = '/static/frames-not-supported.html' # Rewrite javascript URIs elif key in URI_ATTRIBUTES and val is not None: if _contains_js(unescape(val)): element.attributes[key] = "#" elif base and proxy and not (element.tag == "a" and key == 'href'): element.attributes[key] = wrap_url(val, -1, base) element.attributes['_portia_%s' % key] = val elif base: element.attributes[key] = urljoin(base, val) newdoc.append(serialize_tag(element)) else: text = doc[element.start:element.end] if inserted_comment and text.strip(): newdoc.append('') else: newdoc.append(text) return ''.join(newdoc) ================================================ FILE: slyd/slyd/projects.py ================================================ from __future__ import absolute_import import errno import re from os.path import join from portia_api.errors import BadRequest from portia_api.utils.download import ProjectArchiver, CodeProjectArchiver from storage.backends import ContentFile, FsStorage from storage.projecttemplates import templates # stick to alphanum . and _. Do not allow only .'s (so safe for FS path) _INVALID_PROJECT_RE = re.compile('[^A-Za-z0-9._]|^\.*$') def allowed_project_name(name): return not _INVALID_PROJECT_RE.search(name) class ProjectsManager(object): @classmethod def setup(cls, location, **kwargs): cls.base_dir = location def __init__(self, auth_info): self.auth_info = auth_info self.user = auth_info['username'] self.modify_request = { 'download': self._render_file } self.project_commands = { 'create': self.create_project, 'mv': self.rename_project, 'rm': self.remove_project, 'download': self.download_project } def run(self, callback, **kwargs): return callback(**kwargs) def all_projects(self): raise NotImplementedError def list_projects(self): if 'authorized_projects' in self.auth_info: return self.auth_info['authorized_projects'] else: return list(self.all_projects()) def create_project(self, name): self.validate_project_name(name) project_filename = self.project_filename(name) project_files = { 'project.json': templates['PROJECT'], 'scrapy.cfg': templates['SCRAPY'], 'setup.py': templates['SETUP'] % str(name), 'items.json': templates['ITEMS'], join('spiders', '__init__.py'): '', join('spiders', 'settings.py'): templates['SETTINGS'], } for filename, template in project_files.items(): path = join(project_filename, filename) self.storage.save(path, ContentFile(template, path)) def rename_project(self, from_name, to_name): self.validate_project_name(from_name) self.validate_project_name(to_name) self.storage.move(self.project_filename(from_name), self.project_filename(to_name)) def remove_project(self, name): self.storage.rmtree(self.project_filename(name)) def edit_project(self, name, revision=None): # Do nothing here, but subclasses can use this method as a hook # e.g. to import projects from another source. return def validate_project_name(self, name): if not allowed_project_name(name): raise BadRequest('Bad Request', 'Invalid project name %s.' % name) def copy_data(self, source, destination, spiders, items): raise NotImplementedError def download_project(self, name, spiders=None, version=None, **kwargs): raise NotImplementedError def commit_changes(self): if getattr(self, 'storage', None): self.storage.commit() def _render_file(self, request, request_data, body): name = request_data.get('args')[0].encode('utf-8') request.setHeader('Content-Type', 'application/zip') request.setHeader('Content-Disposition', 'attachment; ' 'filename="%s.zip"' % name) request.setHeader('Content-Length', len(body)) return body def __repr__(self): return '%s(%s)' % (self.__class__.__name__, str(self)) def __str__(self): return '%s' % self.user class FileSystemProjectsManager(ProjectsManager): storage_class = FsStorage basedir = '.' def __init__(self, auth_info): super(FileSystemProjectsManager, self).__init__(auth_info) self.storage = self.storage_class('') self.projectsdir = self.base_dir def all_projects(self): try: dirs, _ = self.storage.listdir(self.projectsdir) return [{'id': project, 'name': project}for project in dirs] except OSError as ex: if ex.errno != errno.ENOENT: raise def project_filename(self, name): return join(self.projectsdir, name) def download_project(self, name, spiders=None, version=None, fmt=None, **kwargs): storage = self.storage_class(self.project_filename(name)) if fmt == u'code': archiver = CodeProjectArchiver(storage, name=name) else: archiver = ProjectArchiver(storage, name=name) return archiver.archive(spiders).read() ================================================ FILE: slyd/slyd/projectspec.py ================================================ from __future__ import absolute_import import getpass import json import re from os.path import join, splitext from scrapy.http import HtmlResponse from slyd.html_utils import html4annotation from slyd.errors import BadRequest from storage.backends import ContentFile, FsStorage def convert_template(template): """Converts the template annotated body for being used in the UI.""" template['annotated_body'] = html4annotation( template['annotated_body'], template['url'], proxy_resources=True) class ProjectSpec(object): resources = ('project', 'items', 'extractors') base_dir = '.' plugins = [] @classmethod def setup(cls, location, **kwargs): cls.base_dir = location def __init__(self, project_name, auth_info): self.project_dir = join(self.base_dir, project_name) self.project_name = project_name self.auth_info = auth_info self.user = auth_info['username'] self.spider_commands = { 'mv': self.rename_spider, 'rm': self.remove_spider, 'mvt': self.rename_template, 'rmt': self.remove_template, } def run(self, callback, **kwargs): return callback(**kwargs) def list_spiders(self): _, files = self.storage.listdir(join(self.project_dir, "spiders")) for fname in files: if fname.endswith(".json"): yield splitext(fname)[0] def spider_with_templates(self, spider): spider_spec = self.resource('spiders', spider) templates = [] for template in spider_spec.get('template_names', []): try: templates.append(self.resource('spiders', spider, template)) except IOError: self.remove_template(spider, template) spider_spec['templates'] = templates return spider_spec def spider_json(self, name): """Loads the spider spec for the given spider name.""" return self.resource('spiders', name) def template_json(self, spider_name, template_name): """Loads the given template. Also converts the annotated body of the template to be used by the annotation UI.""" template = self.resource('spiders', spider_name, template_name) convert_template(template) return template def rename_spider(self, from_name, to_name): if to_name == from_name: return # TODO: Make optional if not re.match('^[a-zA-Z0-9][a-zA-Z0-9_\.-]*$', to_name): raise BadRequest('Bad Request', 'Invalid spider name') if to_name in self.list_spiders(): raise IOError('Can\'t rename spider as a spider with the name, ' '"%s", already exists for this project.' % to_name) self.storage.move(self._rfilename('spiders', from_name), self._rfilename('spiders', to_name)) dirname = self._rdirname('spiders', from_name) if self.storage.isdir(dirname): self.storage.move(dirname, self._rdirname('spiders', to_name)) def remove_spider(self, name): filename = self._rfilename('spiders', name) assert filename.endswith('.json') dirname = filename[:-len('.json')] self.storage.delete(filename) try: self.storage.rmtree(dirname) except IOError: pass def rename_template(self, spider_name, from_name, to_name): template = self.resource('spiders', spider_name, from_name) template['name'] = to_name self.savejson(template, ['spiders', spider_name, to_name]) self.remove_template(spider_name, from_name) spider = self.spider_json(spider_name) spider['template_names'].append(to_name) self.savejson(spider, ['spiders', spider_name]) def remove_template(self, spider_name, name): try: self.storage.delete(self._rfilename('spiders', spider_name, name)) except IOError: pass spider = self.spider_json(spider_name) try: spider['template_names'].remove(name) except ValueError: pass self.savejson(spider, ['spiders', spider_name]) def _rfilename(self, *resources): return join(self.project_dir, *resources) + '.json' def _rdirname(self, *resources): return join(self.project_dir, *resources[:-1]) def _process_extraction_urls(self, urls): if hasattr(urls, 'get'): urls = urls.get('urls', []) if isinstance(urls, dict): return urls.items() return urls def _process_extraction_response(self, url, html): return [(url, HtmlResponse(url, body=html))] def extract_data(self, spider_name, url_info, request): pass def resource(self, *resources): return json.load(self.storage.open(self._rfilename(*resources))) def savejson(self, obj, resources): # convert to json in a way that will make sense in diffs fname = self._rfilename(*resources) self.storage.save(fname, ContentFile( json.dumps(obj, sort_keys=True, indent=4), fname)) def commit_changes(self): if getattr(self, 'storage', None): self.storage.commit() def __repr__(self): return '%s(%s)' % (self.__class__.__name__, str(self)) def __str__(self): return '%s, %s' % (self.project_name, self.user) class FileSystemProjectSpec(ProjectSpec): storage_class = FsStorage def __init__(self, project_name, auth_info): super(FileSystemProjectSpec, self).__init__(project_name, auth_info) self.storage = self.storage_class(project_name, author=getpass.getuser()) ================================================ FILE: slyd/slyd/resource.py ================================================ import json import errno from twisted.web.resource import Resource, NoResource, ErrorPage class SlydJsonErrorPage(ErrorPage): def render(self, request): request.setResponseCode(self.code) request.setHeader(b'content-type', b"application/json") return json.dumps({ 'error': self.brief, 'detail': self.detail }) class SlydJsonNoResource(NoResource, SlydJsonErrorPage): pass class SlydJsonResource(Resource): """Base Resource for Slyd Resources This sets the content type to JSON and handles errors """ def render(self, request): request.setResponseCode(200) request.setHeader('Content-Type', 'application/json') try: return Resource.render(self, request) except IOError as ex: if ex.errno == errno.ENOENT: if request.is_ajax(): return SlydJsonNoResource().render(request) else: return NoResource().render(request) else: raise except ErrorPage as ex: if request.is_ajax(): ex = SlydJsonErrorPage(ex.code, ex.brief, ex.detail) return ex.render(request) def error(self, request, status, why): raise ErrorPage(request, status, why) def bad_request(self, why): self.error(400, "Bad Request", why) def not_found(self, message=None): if message is not None: raise NoResource(message) raise NoResource() def read_json(self, request): try: return json.load(request.content) except ValueError as ex: self.bad_request("Error parsing json. %s" % ex.message) class SlydJsonObjectResource(SlydJsonResource): """Extends SlydJsonResource, converting the returned data to JSON """ def render(self, request): resp = SlydJsonResource.render(self, request) if isinstance(resp, dict): resp = json.dumps(resp) return resp ================================================ FILE: slyd/slyd/server.py ================================================ from twisted.python import log from twisted.python.compat import intToBytes from twisted.web import http from twisted.web.http import _escape from twisted.web.server import Site as WebSite, Request as WebRequest from twisted.web.iweb import IAccessLogFormatter from zope.interface.declarations import provider class Request(WebRequest): def is_ajax(self): req_with = self.requestHeaders.getRawHeaders('X-Requested-With', []) return 'XMLHttpRequest' in req_with def processingFailed(self, reason): if self.is_ajax(): log.err(reason) if self.site.displayTracebacks: body = reason.getTraceback() else: body = b"Processing Failed" self.setResponseCode(http.INTERNAL_SERVER_ERROR) self.setHeader(b'content-type', b"text/plain") self.setHeader(b'content-length', intToBytes(len(body))) self.write(body) self.finish() return reason return WebRequest.processingFailed(self, reason) class Site(WebSite): requestFactory = Request @provider(IAccessLogFormatter) def debugLogFormatter(timestamp, request): """ @return: A combined log formatted log line for the given request. @see: L{IAccessLogFormatter} """ referrer = _escape(request.getHeader(b"referer") or b"-") agent = _escape(request.getHeader(b"user-agent") or b"-") line = ( u'"%(ip)s" - - %(timestamp)s "%(method)s %(uri)s %(protocol)s" ' u'%(code)d %(length)s "%(referrer)s" "%(agent)s"' % dict( ip=_escape(request.getClientIP() or b"-"), timestamp=timestamp, method=_escape(request.method), uri=_escape(request.uri), protocol=_escape(request.clientproto), code=request.code, length=request.sentLength or u"-", referrer=referrer, agent=agent, ) ) return line ================================================ FILE: slyd/slyd/settings/__init__.py ================================================ from __future__ import absolute_import from .base import * try: from local_settings import * except ImportError: pass ================================================ FILE: slyd/slyd/settings/base.py ================================================ """Scrapy settings""" from os.path import join, dirname EXTENSIONS = { 'scrapy.contrib.logstats.LogStats': None, 'scrapy.webservice.WebService': None, 'scrapy.telnet.TelnetConsole': None, 'scrapy.contrib.throttle.AutoThrottle': None } LOG_LEVEL = 'DEBUG' # location of slybot projects - assumes a subdir per project DATA_DIR = join(dirname(dirname(__file__)), 'data') SPEC_DATA_DIR = join(DATA_DIR, 'projects') DJANGO_SETTINGS = 'portia_server.settings' SPEC_FACTORY = { 'PROJECT_SPEC': 'slyd.projectspec.FileSystemProjectSpec', 'PROJECT_MANAGER': 'slyd.projects.FileSystemProjectsManager', 'PARAMS': { 'location': SPEC_DATA_DIR, }, } PLUGINS = [{ "ui": "portiaWeb.annotations-plugin", "web": "slyd.plugins.scrapely_annotations.Annotations", "bot": "slybot.plugins.scrapely_annotations.Annotations", "type": "extraction", "options": { "fillColor": 'rgba(88,150,220,0.4)', "strokeColor": 'rgba(88,150,220,0.4)', "textColor": 'white' } }] # recommended for development - use scrapy to cache http responses # add them to local_settings.py # HTTPCACHE_ENABLED = True # HTTPCACHE_DIR = join(DATA_DIR, 'cache') ================================================ FILE: slyd/slyd/specmanager.py ================================================ from scrapy.utils.misc import load_object class SpecManager(object): def __init__(self, settings): self.settings = settings factory_settings = settings['SPEC_FACTORY'] self.spec_class = load_object(factory_settings['PROJECT_SPEC']) plugins = [] for plugin in settings['PLUGINS']: options = plugin['options'] if 'name' not in options: options['name'] = plugin['ui'].split('.')[-1] plugins.append((load_object(plugin['web']), options)) self.spec_class.setup(**factory_settings['PARAMS']) self.spec_class.plugins = plugins self.manager_class = load_object(factory_settings['PROJECT_MANAGER']) self.manager_class.setup(**factory_settings['PARAMS']) self.capabilities = factory_settings.get('CAPABILITIES', {}) self.customizations = factory_settings.get('CUSTOM', {}) self.capabilities['plugins'] = [ {'component': p['ui'], 'options': p.get('options', {})} for p in factory_settings.get('PLUGINS', settings['PLUGINS'])] if 'API_ROUTES' in factory_settings: self.api_routes = load_object(factory_settings['API_ROUTES']) def project_spec(self, project, auth_info): return self.spec_class(str(project), auth_info) def project_manager(self, auth_info): return self.manager_class(auth_info) ================================================ FILE: slyd/slyd/splash/__init__.py ================================================ ================================================ FILE: slyd/slyd/splash/commands.py ================================================ import contextlib import hashlib import json import logging import re import six import sys import socket as _socket from six.moves.urllib.parse import urlparse from django.utils.functional import cached_property from scrapy import Request from scrapy.settings import Settings from splash.browser_tab import JsError from splash.har.qt import cookies2har from slybot.plugins.scrapely_annotations import Annotations as BotAnnotations from slybot.utils import encode, decode from storage.backends import ContentFile from portia_orm.datastore import data_store_context from portia_orm.models import Project from .utils import extract_data, _get_viewport, _html_path, decoded_html _VIEWPORT_RE = re.compile('^\d{3,5}x\d{3,5}$') _SPIDER_LOG = logging.getLogger('spider') _SETTINGS = Settings() _SETTINGS.set('SPLASH_URL', 'http://splash') class Commands(object): def __init__(self, data, socket, storage): self.data, self.socket, self.storage = data, socket, storage @property def tab(self): return self.socket.tab def cookies(self): cookies_list = self.tab.network_manager.cookiejar.allCookies() message = { '_command': 'cookies', 'cookies': cookies2har(cookies_list) } self.socket.sendMessage(message) def heartbeat(self): return def save_html(self, item_checker=None): data = self.data if item_checker is None: item_checker = ItemChecker(self, data['project'], data['spider'], data['sample']) project = Project(self.storage, id=data['project']) self.socket.spiderspec.project = project spider = project.spiders[data['spider']] samples = spider.samples try: sample = samples[data['sample']] self._update_sample(sample) except (IOError, KeyError): pass # Sample doesn't exist or may not exist yet return {'ok': True} def extract_items(self): """Use latest annotations to extract items from current page""" self._open_tab() project = self.data['project'] spider = self.data['spider'] sample = self.data.get('sample') if not all((project, spider)): return {'type': 'raw'} c = ItemChecker(self, project, spider, sample) # TODO: add option for user to view raw and js items in UI from WS items, changes, changed_values, links = c.extract() return {'links': links, 'items': items, 'changes': changes, 'changed': changed_values, 'type': 'js' if c.using_js else 'raw'} def _load_sample(self, data, project=None): project = project or self.socket.spiderspec.project spiders = project.spiders spider = spiders[data['spider']] samples = spider.samples return samples[data['sample']] def _update_sample(self, sample=None, project=None, data=None): """Recompile sample with latest annotations""" if sample is None: sample = self._load_sample(data, project) path = 'spiders/{}/{}/{{}}.html'.format( self.data['spider'], self.data['sample']) else: path = _html_path(sample) if hasattr(sample, 'dump'): sample = sample.dump() html_path = path.format for name, type_ in (('original_body', 'raw'), ('rendered_body', None)): try: path = html_path(name) html = decode(self.storage.open(path).read()) assert html except (AssertionError, IOError): if not self.tab: six.reraise(*sys.exc_info()) html = None if type_ == 'raw': html = self.tab._raw_html if not html: html = self.tab.html() if html: self.storage.save(path, ContentFile(encode(html), path)) html = decode(html) else: html = '' sample[name] = decode(html) return sample def update_spider(self, spider=None): return self.extract() def load_page(self): """Load page in virtual url from provided url""" if 'url' not in self.data: return {'error': 4001, 'message': 'Required parameter url'} self._open_tab() self.tab.loaded = False meta = self.data.get('_meta', {}) def on_complete(is_error, err_info=None): extra_meta = {'id': meta.get('id')} print('Completed page load') if is_error: msg = 'Unknown error' if err_info is None else err_info.text extra_meta.update(error=4500, reason=msg) else: self.tab.loaded = True with data_store_context(): self.socket.sendMessage(self.metadata(extra_meta)) self.cookies() # Specify the user agent directly in the headers # Workaround for https://github.com/scrapinghub/splash/issues/290 headers = {} if "user_agent" in meta: headers['User-Agent'] = meta['user_agent'] self.tab.go(self.data['url'], lambda: on_complete(False), lambda err=None: on_complete(True, err), baseurl=self.data.get('baseurl'), headers=headers) def interact_page(self): """Execute JS event from front end on virtual tab""" self._open_tab() event = json.dumps(self.data.get('interaction', {})) try: self.tab.evaljs('window.livePortiaPage.sendEvent(%s);' % event) except JsError as e: print(e) self.cookies() def resolve(self): result = {'id': self.data.get('_meta', {}).get('id')} try: url = self.data['url'] parsed = urlparse(url) port = 443 if parsed.scheme == 'https' else 80 _socket.getaddrinfo(parsed.hostname, port) except KeyError: result['error'] = 'Can\'t create a spider without a start url' except _socket.gaierror: result['error'] = 'Could not resolve "%s"' % url return result def metadata(self, extra={}): if not self.tab: return {'_command': 'metadata', 'loaded': False} res = {'_command': 'metadata', 'loaded': self.tab.loaded} if self.tab.loaded: try: url = self.tab.url except RuntimeError: url = '' response = {'headers': {}, # TODO: Get headers 'status': self.tab.last_http_status()} res.update( url=url, fp=hashlib.sha1(url.encode('utf8')).hexdigest(), response=response) res.update(self.extract()) res.update(extra) return res def extract(self): """Run spider on page URL to get extracted links and items""" if (self.tab is None or not self.tab.loaded or not (self.socket.spider or (self.data and self.storage))): return { 'items': [], 'links': {}, } spec = self.socket.spiderspec if spec is not None: c = ItemChecker(self, spec.project, spec.name) items, changes, changed_values, links = c.extract() using_js = c.using_js else: items, changes, changed_values, links, using_js = [], [], [], [], 0 return {'links': links, 'items': items, 'changes': changes, 'changed': changed_values, 'type': 'js' if using_js else 'raw'} def resize(self): """Resize virtual tab viewport to match user's viewport""" try: self.tab.set_viewport(_get_viewport(self.data['size'])) except (KeyError, AttributeError): pass # Tab isn't open. The size will be set when opened def close_tab(self): """Close virtual tab if it is open""" if self.tab is not None and not self.tab._closing: self.tab.close() self.socket.factory[self.socket].tab = None def _open_tab(self): if self.tab is None: meta = self.data.get('_meta', self.data) self.socket.open_tab(meta) def _process_items(items): for i, item in enumerate(items): if isinstance(item, dict): new = {} for key, value in item.items(): if key and key.startswith('_'): continue new[key] = _process_items(value) if isinstance(value, list) \ else value items[i] = new elif isinstance(item, list): items[i] = _process_items(item) return items @contextlib.contextmanager def _restore(spider): annotations = spider.plugins['Annotations'] yield spider.plugins['Annotations'] = annotations def _compare_items(a, b): change, changes = set(), [] lena, lenb = len(a), len(b) if lenb > lena: change = {'missing_items'} for aitem, bitem in zip(a, b): item_changes = {} if aitem == bitem: continue afields, bfields = set(aitem.keys()), set(bitem.keys()) b_not_a = bfields ^ afields if b_not_a: change.add('missing_fields') item_changes.update({k: None for k in b_not_a}) for field in afields: afield, bfield = aitem.get(field), bitem.get(field) if afield == bfield: continue item_changes.update({field: (afield, bfield)}) changes.append(item_changes) return list(change), changes class ItemChecker(object): def __init__(self, command, project, spider=None, sample=None): self.command, self.socket = command, command.socket if isinstance(project, six.string_types): project_name = self.socket.user.project_map.get(project, project) project = Project(command.storage, id=project, name=project_name) self.project = project if not self.socket.spider: try: self.socket.open_spider( {'project': self.project.id, 'spider': spider}, project=project) except KeyError: pass # Ignore extraction as it is not fully set up yet self.spider = spider self.sample = sample if (self.spider and (not self.socket.spider or self.socket.spiderspec.name != spider)): self.socket.open_spider({'project': self.project, 'spider': self.spider}, project=project) @property def raw_html(self): try: raw_html = decoded_html(self.socket.tab, 'raw') # XXX: Some pages only show a 301 page. Load the browser html assert len(raw_html) > 500 except (AttributeError, TypeError, AssertionError): raw_html = self.html return raw_html @cached_property def html(self): return self.socket.tab.html() @cached_property def url(self): try: return self.socket.tab.evaljs('location.href') except JsError: return self.socket.tab.url @cached_property def using_js(self): add_splash_meta = self.socket.spider._add_splash_meta url = self.url return 'splash' in add_splash_meta(Request(url)).meta @cached_property def schemas(self): return self.project.schemas.dump() @cached_property def extractors(self): return self.project.extractors.dump() def data(self): return { 'project': self.project, 'spider': self.spider, 'sample': self.sample } def extract(self): check = self._check_items_with_sample if self.sample else \ self._check_items return check() def _load_items(self, body_field='original_body', live=False): if not self.socket.spider: # TODO: Investigate why spider is None return [], [], [], [] socket, raw_html, html = self.socket, self.raw_html, self.html schemas, extractors, url = self.schemas, self.extractors, self.url spider = socket.spiderspec.spider.copy() spider['body'] = body_field if self.sample: samples = [self.command._update_sample(data=self.data(), project=self.project)] self._check_sample(samples[0]) else: samples = socket.spiderspec.templates spider['templates'] = samples extraction = BotAnnotations() extraction.setup_bot(_SETTINGS, self.socket.spider, spider, schemas, extractors, _SPIDER_LOG) self.socket.spider.plugins['Annotations'] = extraction live_items, js_links = extract_data(url, html, socket.spider, samples) raw_items, links = extract_data(url, raw_html, socket.spider, samples) return live_items, raw_items, links, js_links def _check_items(self): try: js_live_items, js_raw_items, links, js_links = self._load_items( 'rendered_body', True) live_items, raw_items, _, _ = self._load_items() except MissingRequiredError as e: data = [e.schema.id, list(e.fields)] return [], ['missing_required_field'], data, [] raw_links = {l: 'raw' for l in links} links = {l: 'js' for l in js_links} links.update(raw_links) # Decide which items to use if self.using_js: changes, changed_values = _compare_items(js_live_items, raw_items) items = js_live_items if items and not raw_items: changes.append('no_items') else: changes, changed_values = _compare_items(raw_items, js_raw_items) changes.extend(_compare_items(live_items, js_live_items)[0]) items = raw_items if raw_items else live_items items = _process_items(items) return items, changes, changed_values, links def _check_sample(self, sample): sample = self.command._load_sample(self.data()) def _check_item(item): schema = item.schema required = {field.id for field in schema.fields if field.required} annotated = set() for annotation in item.annotations: if hasattr(annotation, 'field'): annotated.add(annotation.field.id) else: _check_item(annotation) missing = required - annotated if missing: raise MissingRequiredError(schema, missing) for item in sample.items: _check_item(item) def _check_items_with_sample(self): with _restore(self.socket.spider): return self._check_items() class MissingRequiredError(Exception): def __init__(self, schema, fields): self.schema, self.fields = schema, fields ================================================ FILE: slyd/slyd/splash/cookies.py ================================================ from splash.cookies import SplashCookieJar from splash.har.qt import cookies2har class PortiaCookieJar(SplashCookieJar): def __init__(self, web_page, socket): super(SplashCookieJar, self).__init__(web_page) self.socket = socket self._last_cookies = None def setCookiesFromUrl(self, cookie_list, url): result = super(PortiaCookieJar, self).setCookiesFromUrl(cookie_list, url) self.update_client_cookies() return result def setAllCookies(self, cookie_list): result = super(PortiaCookieJar, self).setAllCookies(cookie_list) self.update_client_cookies() return result def put_client_cookies(self, cookie_list): """ Set all cookies without updating the client. cookie_list is a list of har cookies""" qt_cookies = [self.har_cookie2qt(c) for c in cookie_list] return super(PortiaCookieJar, self).setAllCookies(qt_cookies) def update_client_cookies(self): cookies = self.allCookies() if self._last_cookies == cookies: return self._last_cookies = cookies self.socket.sendMessage({ '_command': 'cookies', 'cookies': cookies2har(cookies) }) ================================================ FILE: slyd/slyd/splash/css_utils.py ================================================ import re from urllib.parse import urlencode, urlparse from scrapy.utils.url import urljoin_rfc from slybot.utils import decode CSS_IMPORT = re.compile(r'''@import\s*["']([^"']+)["']''') CSS_URL = re.compile(r'''\burl\(("[^"]+"|'[^']+'|[^"')][^)]+)\)''') BAD_CSS = re.compile(r'(-moz-binding|expression\s*\(|javascript\s*:)', re.I) def wrap_url(url, tabid, base=None): url = url.strip() referer = None if base: referer = urlparse(base.strip()).netloc url = urljoin_rfc(base, url) parsed = urlparse(url) referer = referer or parsed.netloc if parsed.scheme == 'data': return url # TODO: process CSS inside data: urls if parsed.scheme not in (b'http', b'https', b'ftp'): return 'data:text/plain,invalid_scheme' return "/proxy?" + urlencode({ "url": url, "referer": referer, "tabid": tabid }) def process_css(css_source, tabid, base_uri): """ Wraps urls in css source. >>> url = 'http://scrapinghub.com/style.css' >>> process_css('@import "{}"'.format(url), 0, url) # doctest: +ELLIPSIS '@import "/proxy?..."' """ def _absolutize_css_import(match): return '@import "{}"'.format(wrap_url(match.group(1), tabid, base_uri).replace('"', '%22')) def _absolutize_css_url(match): url = match.group(1).strip("\"'") return 'url("{}")'.format(wrap_url(url, tabid, base_uri).replace('"', '%22')) css_source = decode(css_source) css_source = CSS_IMPORT.sub(_absolutize_css_import, css_source) css_source = CSS_URL.sub(_absolutize_css_url, css_source) css_source = BAD_CSS.sub('portia-blocked', css_source) return css_source ================================================ FILE: slyd/slyd/splash/ferry.py ================================================ from __future__ import absolute_import from functools import partial import json import os import copy import re from six.moves.urllib_parse import urlparse from autobahn.twisted.resource import WebSocketResource from autobahn.twisted.websocket import (WebSocketServerFactory, WebSocketServerProtocol) from weakref import WeakKeyDictionary, WeakValueDictionary from twisted.internet import defer, task from twisted.python import log from scrapy.settings import Settings from scrapy.utils.serialize import ScrapyJSONEncoder from splash import defaults from splash.browser_tab import BrowserTab, skip_if_closing from splash.network_manager import SplashQNetworkAccessManager from splash.qtutils import drop_request from splash.render_options import RenderOptions from slybot.spider import IblSpider from slybot.utils import decode from portia_api.errors import BaseHTTPError from django.conf import settings from django.db import close_old_connections from storage import create_project_storage from portia_orm.models import Project from portia_orm.datastore import data_store_context from portia_orm.utils import short_guid from portia_api.utils.spiders import load_spider_data from .qtutils import QObject, pyqtSlot, QWebElement from .cookies import PortiaCookieJar from .commands import Commands from .css_utils import process_css, wrap_url from .utils import _DEFAULT_VIEWPORT, ProjectsDict import six text = six.text_type # unicode in py2, str in py3 import txaio txaio.use_twisted() _DEFAULT_USER_AGENT = ('Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 ' '(KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36') IGNORED_TYPES = (b'video/', b'audio/', b'application/ogg') MEDIA_EXTENSIONS = ( b'.aac', b'.avi', b'.mid', b'.mpeg', b'.oga', b'.ogv', b'.ogx', b'.swf', b'.wav', b'.weba', b'.webm', b'.xul', b'.3gp', b'.3g2' ) STORED_TYPES = (b'text/html', b'text/xhtml', b'text/xml', b'text/plain', b'text/css', b'image/', b'application/font') STORED_EXTENSIONS = (b'.jpg', b'.jpeg', b'.png', b'.webp', b'.gif', b'.svg', b'.css', b'.xml', b'.html', b'.htm', b'.xhtml', b'.woff', b'.woff2', b'.ttf', b'.otf', b'.eot') def _is_xml(accepts): if accepts.startswith(b'application/'): has_xml = accepts.find(b'xml') if has_xml > 0: semicolon = accepts.find(b';') if semicolon < 0 or has_xml < semicolon: return True return False def wrap_callback(connection, callback, retries=0, **parsed): result = callback(**parsed) if hasattr(parsed.get('storage'), '_working_tree'): parsed['storage'].commit() return result def create_ferry_resource(factory): return FerryWebSocketResource(factory) class PortiaNetworkManager(SplashQNetworkAccessManager): _raw_html = None def createRequest(self, operation, request, outgoingData=None): reply = super(PortiaNetworkManager, self).createRequest( operation, request, outgoingData) if getattr(self, 'closed', False): return reply try: url = six.binary_type(request.url().toEncoded()) frame_url = six.binary_type( self.tab.web_page.mainFrame().requestedUrl().toEncoded()) if url == frame_url: self._raw_html = '' self._url = '' reply.readyRead.connect(self._ready_read) except: log.err() finally: return reply def _ready_read(self): reply = self.sender() self._raw_html = (self._raw_html + six.binary_type( reply.peek(reply.bytesAvailable()))) self._url = six.text_type(reply.url().toString()) class PortiaBrowserTab(BrowserTab): @property def url(self): """ Current URL """ if self._closing: return '' return decode(self.web_page.mainFrame().url().toString()) @skip_if_closing def evaljs(self, *args, **kwargs): return super(PortiaBrowserTab, self).evaljs(*args, **kwargs) class FerryWebSocketResource(WebSocketResource): def __init__(self, factory): FerryServerProtocol.assets = factory.assets WebSocketResource.__init__(self, factory) def render(self, request): request.requestHeaders.setRawHeaders('X-Auth-Info', [json.dumps(request.auth_info)]) return WebSocketResource.render(self, request) class User(object): _by_id = WeakValueDictionary() def __init__(self, auth, tab=None, spider=None, spiderspec=None): self.auth = auth self.authorized_projects = auth.get('authorized_projects', None) self.project_map = ProjectsDict(auth) self.tab = tab self.spider = spider self.spiderspec = spiderspec self.tabid = id(self) User._by_id[self.tabid] = self @classmethod def findById(cls, tabid): return cls._by_id.get(tabid, None) @property def name(self): return self.auth.get('username', '') def __getattr__(self, key): try: return self.auth[key] except KeyError: name = self.__class__.__name__ raise AttributeError('"%s" has no attribute "%s"' % (name, key)) class SpiderSpec(object): def __init__(self, project, name, spider, items, extractors): self.project = project self.name = name self._spider = spider self._items = items self._extractors = extractors @property def spider(self): return copy.deepcopy(self._spider) @property def items(self): return copy.deepcopy(self.items) @property def extractors(self): return copy.deepcopy(self._extractors) @property def templates(self): return self.spider['templates'] def __repr__(self): return '{}({})'.format(self.__class__.__name__, str(self)) def __str__(self): return '{}, {}'.format(self.project, self.name) class PortiaJSApi(QObject): def __init__(self, protocol): super(PortiaJSApi, self).__init__() self.protocol = protocol self.call = None @pyqtSlot(QWebElement) def returnElement(self, element): """Hack to return an DOM node as a QWebElement instead of QVariant(QVariantMap) """ self.element = element def getReturnedElement(self): element = self.element self.element = None return element @pyqtSlot('QString', 'QString', result='QString') def processCss(self, css, baseuri): return process_css(text(css), self.protocol.user.tabid, text(baseuri)) @pyqtSlot('QString', 'QString', result='QString') def wrapUrl(self, url, baseuri): return wrap_url(text(url), self.protocol.user.tabid, text(baseuri)) @pyqtSlot('QString') def log(self, s): print(s) @pyqtSlot('QString') def sendMessage(self, message): message = text(message) # Allocation bug somewhere leaves null characters at the end. message = message.strip('\x00') try: command, data = json.loads(message) except ValueError as e: return log.err(ValueError( "%s JSON head: %r tail: %r" % (e.message, message[:100], message[-100:]) )) self.protocol.sendMessage({ '_command': command, '_data': data }) if command == 'mutation' and not self.call: self.call = task.deferLater(self.protocol.factory.reactor, 1, self.extract) def extract(self): commands = Commands({}, self.protocol, None) self.protocol.sendMessage(commands.metadata()) self.call = None def is_blacklisted(url): return urlparse(url).netloc in settings.BLACKLIST_URLS def blacklist_error(data, socket): meta = data.get('_meta', {}) extra_meta = {'id': meta.get('id')} msg = "Sorry Portia doesn't support this page :(" extra_meta.update(error=4500, reason=msg) commands = Commands({}, socket, None) socket.sendMessage(commands.metadata(extra_meta)) class FerryServerProtocol(WebSocketServerProtocol): _handlers = { 'load': 'load_page', 'interact': 'interact_page' } assets = './' settings = Settings() @property def tab(self): return self.factory[self].tab @property def spider(self): return self.factory[self].spider @property def spiderspec(self): return self.factory[self].spiderspec @property def user(self): return self.factory[self] def onConnect(self, request): try: auth_info = json.loads(request.headers['x-auth-info']) except (KeyError, TypeError): return self.session_id = '' self.auth_info = auth_info self.factory[self] = User(auth_info) def onOpen(self): if self not in self.factory: self.sendClose(1000, 'Invalid Connection missing required ' 'parameters') def onMessage(self, payload, isbinary): close_old_connections() payload = payload.decode('utf-8') data = json.loads(payload) project = data.get('project', data.get('_meta', {}).get('project')) storage = create_project_storage(project, author=self.user) projects = storage.__class__.get_projects(self.user) if project and str(project) not in projects: self.sendMessage({'status': 4004, 'message': 'Project not found'}) return deferred = defer.maybeDeferred( wrap_callback, None, self._on_message, storage=storage, data=data) deferred.addCallbacks(self.sendMessage, partial(self.send_error, data)) def _on_message(self, storage, data): if '_meta' in data and 'session_id' in data['_meta']: self.session_id = data['_meta']['session_id'] if is_blacklisted(data.get('url', '')): blacklist_error(data, self) return command = data['_command'] command = self._handlers.get(command, command) with data_store_context(): commands = Commands(data, self, storage) result = getattr(commands, command, lambda: None)() if result: result.setdefault('_command', data.get('_callback', command)) if '_meta' in data and 'id' in data['_meta']: result['id'] = data['_meta']['id'] return result def onClose(self, was_clean, code, reason): if self in self.factory: if self.tab is not None: self.tab.close() self.tab.network_manager.closed = True msg_data = {'session': self.session_id, 'session_time': 0, 'user': self.user.name} msg = (u'Websocket Closed: id=%(session)s t=%(session_time)s ' u'user=%(user)s command=' % (msg_data)) log.err(msg) def sendMessage(self, payload, is_binary=False): if isinstance(payload, dict) and '_command' in payload: data = json.dumps( payload, cls=ScrapyJSONEncoder, sort_keys=True).encode('utf-8') super(FerryServerProtocol, self).sendMessage(data, is_binary) def send_error(self, data, failure): e = failure.value command = data.get('_callback', data.get('_command')) id_ = data.get('_meta', {}).get('id') if isinstance(e, BaseHTTPError): code, reason, message = e.status, e.title, e.body elif isinstance(e, KeyError): requested_command = data.get('_command') code = 4000 reason = "Unknown command" if requested_command: message = 'No command named "%s" found.' % requested_command else: message = "No command received" else: code = 500 reason = "Internal Server Error" message = "An unexpected error has occurred." log.err(failure) event_id = getattr(failure, 'sentry_event_id', None) if event_id: message = "%s (Event ID: %s)" % (message, event_id) response = { 'error': code, 'reason': reason, 'message': message, } if command: response['_command'] = command if id_: response['id'] = id_ self.sendMessage(response) def getElementByNodeId(self, nodeid): self.tab.web_page.mainFrame().evaluateJavaScript( 'livePortiaPage.pyGetByNodeId(%s)' % nodeid ) return self.js_api.getReturnedElement() def open_tab(self, meta=None): if meta is None: meta = {} manager = SplashQNetworkAccessManager( request_middlewares=[], response_middlewares=[], verbosity=defaults.VERBOSITY ) manager.setCache(None) data = {} data['uid'] = id(data) self.factory[self].tab = PortiaBrowserTab( network_manager=manager, splash_proxy_factory=None, verbosity=defaults.VERBOSITY, render_options=RenderOptions(data, defaults.MAX_TIMEOUT), visible=True, ) manager.tab = self.tab self.tab.register_callback('on_request', self._configure_requests) self.tab.register_callback('on_response', self._set_tab_html) main_frame = self.tab.web_page.mainFrame() cookiejar = PortiaCookieJar(self.tab.web_page, self) manager.cookiejar = cookiejar manager.setCookieJar(cookiejar) if meta.get('cookies'): cookiejar.put_client_cookies(meta['cookies']) self.tab.web_page.loadStarted.connect(self._on_load_started) main_frame.loadFinished.connect(self._on_load_finished) self.js_api = PortiaJSApi(self) main_frame.javaScriptWindowObjectCleared.connect( self._on_javascript_window_cleared) main_frame.initialLayoutCompleted.connect(self._on_layout_completed) self.tab.set_images_enabled(True) self.tab.set_viewport(meta.get('viewport') or _DEFAULT_VIEWPORT) self.tab.set_user_agent(meta.get('user_agent') or _DEFAULT_USER_AGENT) self.tab.loaded = False def _on_load_started(self): self.load_id = short_guid() self.sendMessage({'_command': 'loadStarted', 'id': self.load_id, 'url': self.tab.url}) self.tab.initial_layout_completed = False return True def _on_load_finished(self, ok=False): if getattr(self.tab, '_raw_url', None) != self.tab.url: page = self.tab.web_page page.triggerAction(page.ReloadAndBypassCache, False) # Avoid infinite reload loop self.tab._raw_url = self.tab.url self.sendMessage({'_command': 'loadFinished', 'url': self.tab.url, 'id': getattr(self, 'load_id', None)}) return True def _configure_requests(self, request, operation, data): if request.hasRawHeader(b'Accept'): url = six.binary_type(request.url().toEncoded()) url_path = urlparse(url).path.lower() accepts = bytes(request.rawHeader(b'Accept')).lower() if (accepts.startswith(STORED_TYPES) or _is_xml(accepts) or url_path.endswith(STORED_EXTENSIONS)): request.track_response_body = True elif (accepts.startswith(IGNORED_TYPES) or url_path.endswith(MEDIA_EXTENSIONS)): drop_request(request) def _set_tab_html(self, reply, har, content): url = reply.url().toString() if content is not None and url == self.tab.url: self.tab._raw_html = decode(content) self.tab._raw_url = decode(url) def _on_layout_completed(self): if not getattr(self.tab, 'initial_layout_completed', False): self.populate_window_object() self.tab.initial_layout_completed = True def _on_javascript_window_cleared(self): if getattr(self.tab, 'initial_layout_completed', False): self.populate_window_object() def populate_window_object(self): main_frame = self.tab.web_page.mainFrame() main_frame.addToJavaScriptWindowObject('__portiaApi', self.js_api) path = os.path.join( self.assets, b'splash_content_scripts').decode('utf-8') self.tab.run_js_files(path, handle_errors=False) def open_spider(self, meta, storage=None, project=None): if not (meta.get('project') and meta.get('spider')): return {'error': 4005, 'reason': 'No project specified'} if (self.user.authorized_projects is not None and meta['project'] not in self.user.authorized_projects and not self.user.staff): return {'error': 4004, 'reason': 'Project "%s" not found' % meta['project']} spider_name = meta['spider'] if project is None: project = Project(storage, id=meta.get('project')) try: spider_model = project.spiders[spider_name] except (IOError, KeyError): return {'error': 4004, 'reason': 'Spider "%s" not found' % spider_name} spider_name, spider, items, extractors = load_spider_data(spider_model) if not self.settings.get('SPLASH_URL'): self.settings.set('SPLASH_URL', 'portia') self.factory[self].spider = IblSpider(spider_name, spider, items, extractors, self.settings) self.factory[self].spiderspec = SpiderSpec( project, spider_name, spider, items, extractors) def __repr__(self): return '{}({})'.format(self.__class__.__name__, str(self)) def __str__(self): tab, spider, spec = '', '', '' if self.tab: try: tab = '{}({})'.format( self.tab.__class__.__name__, self.tab.url) except RuntimeError: tab = 'MISSING' if self.spider: spider = '{}({})'.format( self.spider.__class__.__name__, self.spider.name) if self.spiderspec: spec = str(self.spiderspec) return ', '.join(filter(bool, (tab, spider, spec))) class FerryServerFactory(WebSocketServerFactory): def __init__(self, uri, assets='./'): WebSocketServerFactory.__init__(self, uri) self._peers = WeakKeyDictionary() self.assets = assets def __getitem__(self, key): if key in self._peers: return self._peers[key] return None def __setitem__(self, key, value): self._peers[key] = value def __contains__(self, key): if self._peers.get(key) is not None: return True return False def __repr__(self): return 'Ferry(%s)' % ', '.join('User(%s)' % ( urlparse(user.tab.url).netloc for user in self._peers.values() if user.tab)) ================================================ FILE: slyd/slyd/splash/proxy.py ================================================ from __future__ import absolute_import import functools import requests from base64 import b64decode from twisted.internet.threads import deferToThread from twisted.internet.defer import CancelledError from twisted.web.resource import Resource from twisted.web.server import NOT_DONE_YET from twisted.python import log from slybot.utils import encode from .qtutils import QNetworkRequest, to_py from .ferry import User, is_blacklisted from .css_utils import process_css class ProxyResource(Resource): def render_GET(self, request): if not request.auth_info or not request.auth_info.get('username', None): return self._error(request, 403, 'Auth required') for arg in (b'url', b'referer', b'tabid'): if arg not in request.args or len(request.args[arg]) != 1: return self._error( request, 400, b'Argument required: %s' % arg) url = request.args[b'url'][0] if is_blacklisted(url): return self._error(request, 404, b'Not Found') referer = request.args[b'referer'][0] try: tabid = int(request.args[b'tabid'][0]) except (ValueError, TypeError): return self._error(request, 400, b'Tab must exist' % arg) return self._load_resource(request, url, referer, tabid) def _load_resource(self, request, url, referer, tabid=None): # It's not easy to cancel a request that's being made by splash, # because it does't return the QNetworkReply and when redirecting the # current QNetworkReply changes, so if the client closes the connection # while fetching the content we simply note it in this object and let # the request finish without aborting. user = User.findById(tabid) connection_status = {"finished": False} cb = functools.partial(self.end_response, request, url, referer, connection_status, tabid) if not (user and user.tab): # No browser session active, proxy resource instead return self._load_resource_proxy(request, url, referer, cb) if request.auth_info['username'] != user.auth['username']: return self._error( request, 403, b"You don't own that browser session") try: entry = next((entry for entry in user.tab.har()['log']['entries'] if entry['request']['url'] == url), None) response = entry['response'] content = b64decode(response['content']['text']) for header in response['headers']: name, value = header['name'], header['value'] name_lower = name.lower() if (name.startswith(('c', 'C')) and name_lower == 'content-type' and value.strip().startswith('text/css')): content = process_css(content, tabid, url) if (name_lower.startswith('x-') or name_lower in {'server', 'date', 'connection', 'transfer-encoding', 'content-encoding'}): continue request.responseHeaders.addRawHeader(name.encode('ascii'), value.encode('ascii')) request.setResponseCode(response['status']) return content except (AttributeError, KeyError, AssertionError, TypeError): pass request.notifyFinish().addErrback(self._requestDisconnect, None, connection_status) try: user.tab.http_client.get(url, cb, headers={'referer': referer}) return NOT_DONE_YET except: # Sometimes the browser frame has been freed and we get a # "underlying C/C++ object has been deleted" error. Not sure if we # can do something to avoid it, but if it happens we proxy the # resource instead of recovering it from splash. log.err() return self._load_resource_proxy(request, url, referer, cb) def _load_resource_proxy(self, request, url, referer, cb): d = deferToThread(requests.get, url, headers={'referer': referer}) d.addCallback(cb) d.addErrback(self._requestError, request) request.notifyFinish().addErrback(self._requestDisconnect, deferred=d) return NOT_DONE_YET def _requestError(self, err, request): if not err.check(CancelledError): request.setResponseCode(500) request.write('Error fetching the content') request.finish() def _requestDisconnect(self, err, deferred=None, connection_status=None): if deferred: deferred.cancel() if connection_status: connection_status["finished"] = True def end_response(self, request, original_url, referer, connection_status, tabid, reply): if connection_status["finished"]: return if hasattr(reply, 'readAll'): content = bytes(reply.readAll()) status_code = to_py(reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)) if status_code == 400: return self._load_resource(request, original_url, referer) request.setResponseCode(status_code or 500) else: content = b''.join(chunk for chunk in reply.iter_content(65535)) request.setResponseCode(reply.status_code) headers = { b'cache-control': b'private', b'pragma': b'no-cache', b'content-type': b'application/octet-stream', } for header in (b'content-type', b'cache-control', b'pragma', b'vary', b'max-age'): if hasattr(reply, 'hasRawHeader') and reply.hasRawHeader(header): headers[header] = bytes(reply.rawHeader(header)) elif hasattr(reply, 'headers') and header in reply.headers: headers[header] = bytes(reply.headers.get(header)) if header in headers: request.setHeader(header, headers[header]) if bytes(headers[b'content-type']).strip().startswith(b'text/css'): content = encode(process_css(content, tabid, original_url)) request.write(content) request.finish() def _error(self, request, code, message): request.setResponseCode(code) return message ================================================ FILE: slyd/slyd/splash/qtutils.py ================================================ try: from PyQt5.QtCore import QObject from PyQt5.QtCore import pyqtSlot from PyQt5.QtWebKit import QWebElement from PyQt5.QtNetwork import QNetworkRequest except ImportError: from PyQt4.QtCore import QObject from PyQt4.QtCore import pyqtSlot from PyQt4.QtWebKit import QWebElement from PyQt4.QtNetwork import QNetworkRequest def to_py(obj): if hasattr(obj, 'toPyObject'): return obj.toPyObject() return obj ================================================ FILE: slyd/slyd/splash/utils.py ================================================ import six from scrapy.http import HtmlResponse, Request from scrapy.item import DictItem from portia_api.errors import BaseHTTPError from slybot.utils import encode, decode _DEFAULT_VIEWPORT = '1240x680' def decoded_html(tab, type_=None): if type_ == 'raw': stated_encoding = tab.evaljs('document.characterSet') return decode(tab._raw_html or tab.html(), default=stated_encoding) return tab.html() def extract_data(url, html, spider, templates): items, links = [], [] if isinstance(html, six.text_type): html = encode(html) for value in spider.parse(page(url, html)): if isinstance(value, Request): links.append(value.url) elif isinstance(value, DictItem): value['_template_name'] = _get_template_name(value['_template'], templates) items.append(value._values) else: raise ValueError("Unexpected type %s from spider" % type(value)) return items, links def page(url, html): return HtmlResponse(url, 200, {}, html, encoding='utf-8') def _html_path(sample): path = sample.storage_path(sample)[:-len('.json')].strip('/') return '{}/{{}}.html'.format(path) def _get_template_name(template_id, templates): for template in templates: if template['page_id'] == template_id: return template['name'] def _should_load_sample(sample): a = sample.get('plugins', {}).get('annotations-plugin', {}).get('extracts') if (sample.get('annotated_body', '').count('data-scrapy') > 1 or (sample.get('original_body') and a)): return True return False def _get_viewport(viewport): """Check that viewport is valid and within acceptable bounds. >>> f = '99x99 99x100 100x99 4097x4097 1280.720 wxy'.split() >>> p = '100x100 1280x720 4096x2160'.split() >>> _get_viewport(None) == _DEFAULT_VIEWPORT True >>> all(_get_viewport(i) == _DEFAULT_VIEWPORT for i in f) True >>> all(_get_viewport(i) == i for i in p) True """ try: assert viewport is not None v = viewport.split('x') if len(v) != 2: raise ValueError('Viewport must have width and height') w, h = int(v[0]), int(v[1]) if not (99 < w < 4097 and 99 < h < 4097): raise ValueError('Viewport out of bounds') except (AssertionError, TypeError, ValueError): return _DEFAULT_VIEWPORT return viewport class BaseWSError(BaseHTTPError): @property def status(self): return self._status + 4000 class BadRequest(BaseWSError): _status = 400 class Forbidden(BaseWSError): _status = 403 class NotFound(BaseWSError): _status = 404 class InternalServerError(BaseWSError): _status = 500 class ProjectsDict(dict): def __init__(self, auth): self.allow_all = False if 'projects_data' in auth: for project in auth['projects_data']: self[project['id']] = project['name'] elif 'authorized_projects' in auth: for project_id in auth['authorized_projects']: self[project_id] = project_id else: self.allow_all = True self.staff = auth.get('staff', False) def __getitem__(self, key): try: return super(ProjectsDict, self).__getitem__(key) except KeyError: if self.allow_all or self.staff: return key raise def __contains__(self, key): if self.allow_all or self.staff: return True return super(ProjectsDict, self).__contains__(key) ================================================ FILE: slyd/slyd/tap.py ================================================ ''' The module is used by the Twisted plugin system (twisted.plugins.slyd_plugin) to register twistd command to manage slyd server. The command can be used with 'twistd slyd'. ''' from __future__ import absolute_import from os import listdir, environ from os.path import join, dirname, isfile, abspath from twisted.python import usage from twisted.web.resource import Resource from twisted.web.static import File from .resource import SlydJsonObjectResource from .server import Site, debugLogFormatter DEFAULT_PORT = 9001 DEFAULT_DOCROOT = abspath(join(dirname(dirname(__file__)), '..', 'portiaui', 'dist')) class Options(usage.Options): optParameters = [ ['port', 'p', DEFAULT_PORT, 'Port number to listen on.', int], ['docroot', 'd', DEFAULT_DOCROOT, 'Default doc root for static media.'] ] class Capabilities(SlydJsonObjectResource): isLeaf = True def __init__(self, spec_manager): self.spec_manager = spec_manager def render_GET(self, request): return { 'capabilities': self.spec_manager.capabilities, 'custom': self.spec_manager.customizations, 'username': request.auth_info.get('username'), } def configure_django(settings): import django environ.setdefault('DJANGO_SETTINGS_MODULE', settings['DJANGO_SETTINGS']) django.setup() def create_root(config, settings_module): from scrapy.settings import Settings settings = Settings() settings.setmodule(settings_module) configure_django(settings) from .authmanager import AuthManager from slyd.splash.ferry import (FerryServerProtocol, FerryServerFactory, create_ferry_resource) from slyd.splash.proxy import ProxyResource root = Resource() static = Resource() docroot = config['docroot'] if hasattr(docroot, 'encode'): docroot = docroot.encode('utf-8') for file_name in listdir(docroot): file_path = join(docroot, file_name) if isfile(file_path): static.putChild(file_name, File(file_path)) static.putChild(b'main.html', File(join(docroot, b'index.html'))) root.putChild(b'static', static) root.putChild(b'assets', File(join(docroot, b'assets'))) root.putChild(b'fonts', File(join(docroot, b'assets', b'fonts'))) root.putChild(b'', File(join(docroot, b'index.html'))) # add websockets for communicating with splash factory = FerryServerFactory('ws://127.0.0.1:%d' % config['port'], assets=docroot) factory.protocol = FerryServerProtocol websocket = create_ferry_resource(factory) root.putChild(b'ws', websocket) root.putChild(b'proxy', ProxyResource()) auth_manager = AuthManager(settings) return auth_manager.protectResource(root) def makeService(config, settings_module=None): if settings_module is None: import slyd.settings as settings_module root = create_root(config, settings_module) site = Site(root, logFormatter=debugLogFormatter) return site ================================================ FILE: slyd/twisted/plugins/slyd_plugin.py ================================================ """Registers 'twistd slyd' command.""" from twisted.application.service import ServiceMaker finger = ServiceMaker( 'slyd', 'slyd.tap', 'A server for creating scrapely spiders', 'slyd') ================================================ FILE: splash_utils/compile_slybot.sh ================================================ #!/bin/bash { echo ";(function(){" cat '../portiaui/bower_components/es5-shim/es5-shim.js' # Page actions scripts cat 'waitAsync.js' cat 'perform_actions.js' echo '})();' } > ../slybot/slybot/splash-script-combined.js ================================================ FILE: splash_utils/filters/easylist.txt ================================================ [Adblock Plus 2.0] ! Checksum: gz3aDcNyBxcKFlEoU0H3pw ! Version: 201505140830 ! Title: EasyList ! Last modified: 14 May 2015 08:30 UTC ! Expires: 4 days (update frequency) ! Homepage: https://easylist.adblockplus.org/ ! Licence: https://easylist-downloads.adblockplus.org/COPYING ! ! Please report any unblocked adverts or problems ! in the forums (https://forums.lanik.us/) ! or via e-mail (easylist.subscription@gmail.com). ! !-----------------------General advert blocking filters-----------------------! ! *** easylist:easylist/easylist_general_block.txt *** &ad_box_ &ad_channel= &ad_classid= &ad_height= &ad_keyword= &ad_network_ &ad_number= &ad_type= &ad_type_ &ad_url= &ad_zones= &adbannerid= &adclient= &adcount= &adgroupid= &admeld_ &admid= &adname= &adnet= &adnum= &adpageurl= &adsafe= &adserver= &adsize= &adslot= &adslots= &adsourceid= &adspace= &adstype= &adType=PREROLL& &adunit= &adurl= &adv_keywords= &advert_ &advertiserid= &advid= &advtile= &adzone= &banner_id= &clicktag=http &customSizeAd= &displayads= &expandable_ad_ &gIncludeExternalAds= &googleadword= &jumpstartadformat= &largead= &maxads= &popunder= &program=revshare& &prvtof=*&poru= &show_ad_ &showad= &simple_ad_ &smallad= &strategy=adsense& &type=ad& &UrlAdParam= &video_ads_ &videoadid= &view=ad& +advertorial. +adverts/ -2/ads/ -2011ad_ -300x100ad2. -ad-001- -ad-180x150px. -ad-200x200- -ad-24x24. -ad-300x250. -ad-313x232. -ad-340x400- -ad-400. -ad-banner. -ad-big. -ad-bottom- -ad-button- -ad-category- -ad-choices. -ad-column- -ad-data/ -ad-ero- -ad-exo- -ad-gif1- -ad-home. -ad-hrule- -ad-hrule. -ad-iframe/ -ad-large. -ad-left. -ad-limits. -ad-loading. -ad-manager/$~stylesheet -ad-marker. -ad-mpu+ -ad-new_ -ad-right. -ad-rotators/ -ad-server/ -ad-sidebar- -ad-tile. -ad-top. -ad-unit. -ad-unit/ -ad-util- -ad-util. -ad-vertical- -ad-zone. -ad.jpg.pagespeed. -ad.jpg? -ad.jsp| -ad.php? -ad/main. -ad/right_ -ad1. -ad2. -ad3. -Ad300x250. -Ad300x90- -ad4. -ad5. -ad_125x125. -ad_banner- -ad_injector/ -ad_leaderboard/ -adap. -adblack- -adcentre. -adchain. -adhelper. -adhere2. -adimage- -admarvel/ -adrotation. -ads-180x -ads-728x -ads-banner. -ads-bottom. -ads-iframe. -ads-init& -ads-management/ -ads-manager/ -ads-placement. -ads-right. -ads-widget? -ads.generated. -ads.gif -ads.js? -ads.php? -ads.swf -ads/728x -ads/oas/ -Ads_728x902. -ads_9_3. -Ads_Billboard_ -adscript. -adsense2. -adserver- -adserver/ -adsonar. -adspace. -adspace_ -adspot- -adswizz- -adsystem- -adtechfront. -adtopbanner- -adtrack. -adv-v1/ -adv.jpg -adv.js -advert-label- -advert.jpg? -advert.swf -advert1. -advert2. -advert3. -advertise. -advertise/ -advertise01. -advertisement-icon. -advertisement. -advertisement_ -advertising_ -advertisment- -adwords. -affiliate-link. -affiliates/img_ -article-ads- -article-advert- -banner-ad- -banner-ad. -banner-ads- -banner.swf? -banner468x60. -bannerads/ -bg_ads. -billboard-ads/ -bin/ad_ -blog-ad- -book-ad- -Box-Ad. -box2-ad? -content-ad. -contest-ad. -cpm-ad. -cpm-ads. -criteo. -dfp-ads/ -euads. -fe-ads/ -feed-ads. -fleshlight2. -floater_ads_ -floorboard-ads/ -footerads- -footerads. -gallery_ad/ -games/ads/ -google-ads- -google-ads/ -google2-ad- -gpt-ad- -housead- -iframe-ad. -iframe-ads/ -image-ad. -image/Ads/ -images/ad- -img/ads/ -inspire-ad. -intern-ads/ -layer-ad. -layer-ads/ -leaderboard-ad- -load-ads. -NewAd. -news-ad- -newsletter-ad- -NewStockAd- -online-advert. -page-ad. -page-ad? -page-peel/ -panel-ad. -panel_ad_ -peel-ads- -permads. -pop-under/ -popexit. -popunder. -popup-ad. -popup-ads- -printhousead- -publicidad. -rectangle/ad- -Results-Sponsored. -right-ad. -rightrailad- -rollout-ad- -scrollads. -seasonal-ad. -show-ads. -side-ad- -Skyscraper-Ad. -skyscrapper160x600. -small-ad. -source/ads/ -sponsor-ad. -sponsored-links- -strip-ads- -template-ads/ -text-ads. -theme/ads/ -third-ad. -top-ad. -top-ads. -us/ads/ -web-ad- -Web-Ad. -Web-Ads. -web-advert- -Web-Advert. -webad1. -your-ads-here. .1d/ads/ .a3s?n=*&zone_id= .ace.advertising. .ad-cloud. .ad-sys. .ad-traffic. .ad.final. .ad.footer. .ad.json? .ad.page. .ad.premiere. .ad1.nspace .adbanner. .adbutler- .adcenter. .adforge. .adframesrc. .adlabs.$domain=~adlabs.ru .admarvel. .adnetwork. .adpartner. .adplacement= .adresult.$domain=~adresult.ch .adriver.$~object-subrequest .adru. .ads-and-tracking. .ads-lazy. .ads-min. .ads-tool. .ads.core. .ads.css .ads.darla. .ads.loader- .ads.zones. .ads_clickthru. .adsbox. .adsense. .adserv/ .adserver. .adserver01. .adserver1. .adService. .adspace. .adsremote. .adtech_ .adtooltip& .adv.cdn. .advert.$domain=~advert.ly .AdvertismentBottom. .advertmarket. .adwolf. .ae/ads/ .ar/ads/ .ashx?ad= .ashx?AdID= .asp?coad .aspx?ad= .aspx?adid= .at/ads/ .au/ads/ .banner%20ad. .bbn.by/ .biz/ad. .biz/ad/ .biz/ad2/ .biz/ads/ .bns1.net/ .box.ad. .br/ads/ .ca/ads/ .cc/ads/ .cfm?ad= .cgi?ad= .ch/ads/ .ch/adv/ .clkads. .co/ads/ .co/ads? .com/?ad= .com/?wid= .com/a?network .com/a?pagetype .com/a?size .com/ad.$domain=~ad-tuning.de .com/ad/$domain=~channel4.com|~watchever.de .com/ad2/ .com/ad6/ .com/ad? .com/adclk? .com/adds/ .com/adgallery .com/adinf/ .com/adlib/ .com/adlib_ .com/adpicture .com/ads- .com/ads. .com/ads/$image,object,subdocument .com/ads? .com/ads_ .com/adv/ .com/adv3/ .com/adv? .com/adv_ .com/adx/ .com/adx_ .com/adz/ .com/bads/ .com/doubleclick/ .com/gads/ .com/im-ad/ .com/im_ad/ .com/iplgadshow .com/js.ng/ .com/js/ad. .com/js/ads/ .com/js/adsense .com/miads/ .com/peels/ .com/pm/ad- .com/promodisplay? .com/ss/ad/ .com/video-ad- .cz/affil/ .cz/bannery/ .dartconfig.js .displayAds& .eg/ads/ .eu/ads/ .eu/adv/ .fm/ads/ .gg/ads/ .gif?ad= .gr/ads/ .hk/ads/ .homad. .HomepageAdvertismentBottom. .html?ad= .html?ad_ .html?clicktag= .iads.js .ie/ads/ .il/ads/ .in/ads/ .info/ad_ .info/ads- .info/ads/ .initdoubleclickadselementcontent? .internads. .is/ads/ .jp/ads/ .jsp?adcode= .ke/ads/ .lazyload-ad- .lazyload-ad. .link/ads/ .lk/ads/ .me/ads- .me/ads/ .mobileads. .mv/ads/ .mx/ads/ .my/ads/ .name/ads/ .net/_adv/ .net/ad- .net/ad/$~object-subrequest .net/ad2/ .net/ad_ .net/adgallery .net/adj; .net/ads- .net/ads. .net/ads/ .net/ads? .net/ads_ .net/adt? .net/adv/ .net/affiliate/ .net/bnr/ .net/flashads .net/gads/ .net/noidadx/ .net/pfadj/ .net/pops.js .net/vghd_ .nl/ad2/ .nl/ads/ .no/ads/ .nu/ads/ .nz/ads/ .oasfile. .openad. .openx. .openxtag.js .openxtag.min.js .org/ad- .org/ad. .org/ad/ .org/ad_ .org/adgallery1 .org/ads- .org/ads/ .org/ads_ .org/adv/ .org/exit.js .org/gads/ .org/pops.js .ph/ads/ .php/ad/ .php/ads/ .php?ad= .php?ad_ .php?adsid= .php?adv= .php?affid= .php?clicktag= .php?nats= .php?zone_id= .php?zoneid= .pk/ads/ .pl/ads/ .popunder.js .popup_im. .popupvideoad. .refit.ads. .rolloverad. .se/?placement=$script,subdocument,third-party .se/ads/ .shortcuts.search. .show_ad_ .sk/ads/ .spider.ad/ .sponsorads. .streamads. .swf?1&clicktag= .swf?2&clicktag= .swf?ad= .swf?click= .swf?clicktag= .swf?clickthru= .swf?iurl=http .swf?link1=http .swf?link=http .swf?popupiniframe= .text-link-ads. .textads. .th/ads/ .to/ads/ .topad. .tv/adl. .tv/ads. .tv/ads/ .twoads. .tz/ads/ .uk/ads/ .uk/adv/ .us/ads/ .vert.ad. .widgets.ad? .ws/ads/ .xxx/ads/ .za/ads. .za/ads/ .zm/ads/ .zw/ads/ /!advert_ /0/ads/* /04/ads- /1/ads/* /120ad. /120ads/* /125x125_banner. /125x125ad. /126_ad. /17/ads/* /1912/ads/* /1afr.php? /2010/ads/* /2010main/ad/* /2011/ads/* /2013/ads/* /2014/ads/* /2015/ads/* /24-7ads. /24adscript. /250x250_advert_ /300-ad- /300250_ad- /300by250ad. /300x250ad. /300x250adbg. /300x250ads. /300x250advert. /300x500_ad /336x280ads. /3pt_ads. /468-banner. /468ad. /468xads. /728_ad_ /728x80topad. /728x90banner. /?addyn|* /?adv_partner /?advideo/* /?view=ad /_/ads/* /_30/ads/* /_ads/* /_affiliatebanners/* /_global/ads/* /_img/ad_ /_js2/oas. /_scripts/_oas/* /_svc/ad/* /a/ads/* /a1/*?sub=$third-party /a2/?sub=$third-party /a2/ads/* /a3/?sub=$third-party /aamsz= /ABAdsv1. /abm.asp? /abm.aspx /abmw.asp /abmw/* /abnl/?begun^ /abnl/?narodads^ /about-these-ads. /absolutebm.aspx? /acc_random= /ad%20banners/* /ad%20images/* /ad-125. /ad-300topleft. /ad-300x250. /ad-300x254. /ad-350x350- /ad-468- /ad-600- /ad-amz. /ad-audit. /ad-banner- /ad-banner. /ad-bckg. /ad-bin/* /ad-bottom. /ad-box- /ad-boxes- /ad-builder. /ad-button1. /ad-callback. /ad-cdn. /ad-channel- /ad-choices- /ad-choices. /ad-creatives- /ad-creatives/* /ad-emea. /ad-engine. /ad-exchange. /ad-feature- /ad-feedback. /ad-flashgame. /ad-format. /ad-frame. /ad-frame/* /ad-gallery.$~stylesheet /ad-half_ /ad-hcm. /ad-header. /ad-home- /ad-hug. /ad-identifier. /ad-ifr. /ad-iframe- /ad-iframe. /ad-iframe? /ad-image. /ad-images/* /ad-ina. /ad-indicator- /ad-inject/* /ad-injection/* /ad-int- /ad-issue. /ad-label- /ad-label. /ad-layering- /ad-layout/* /ad-leaderboard. /ad-left. /ad-letter. /ad-lil. /ad-loader- /ad-loader. /ad-loading. /ad-local. /ad-logger/* /ad-manager/* /ad-managment/* /ad-methods. /ad-minister- /ad-minister. /ad-minister/* /ad-modules/* /ad-nytimes. /ad-offer1. /ad-openx. /ad-plate/* /ad-point/* /ad-position- /ad-pub. /ad-record. /ad-refresh- /ad-refresh. /ad-right2. /ad-ros- /ad-rotator- /ad-serve? /ad-server. /ad-server/* /ad-side/* /ad-sidebar- /ad-skyscraper. /ad-source/* /ad-specs. /ad-sprite. /ad-strip. /ad-studio/* /ad-styles. /ad-tag2. /ad-tandem. /ad-template. /ad-template/* /ad-text. /ad-title. /ad-top- /ad-top. /ad-top/* /ad-topbanner- /ad-unit- /ad-updated- /ad-utilities. /ad-vert. /ad-vertical- /ad-verticalbar. /ad-view- /ad.ashx? /ad.asp? /ad.aspx? /ad.cgi? /ad.code? /ad.css? /ad.epl? /ad.gif| /ad.html? /ad.info. /ad.jsp? /ad.mason? /ad.min. /ad.php3? /ad.php? /ad.php| /ad.popup? /ad.redirect. /ad.sense/* /ad.serve. /ad.valary? /ad.view? /ad.ytn. /ad/600- /ad/728- /ad/?host= /ad/?section= /ad/?site= /ad/a.aspx? /ad/afc_ /ad/article_ /ad/audsci. /ad/banner. /ad/banner/* /ad/banner? /ad/banner_ /ad/bannerdetails/* /ad/bannerimg/* /ad/banners/* /ad/behavpixel. /ad/bin/* /ad/blank. /ad/blog_ /ad/bottom. /ad/card- /ad/common/* /ad/common_ /ad/content/* /ad/cpmstar/* /ad/css/* /ad/directcall/* /ad/empty. /ad/extra/* /ad/extra_ /ad/files/* /ad/frame1. /ad/framed? /ad/generate? /ad/getban? /ad/getbanandfile? /ad/google/* /ad/google_ /ad/html/* /ad/iframe. /ad/iframe/* /ad/image/* /ad/img/* /ad/index. /ad/index/* /ad/inline? /ad/integral- /ad/inventory/* /ad/jsonp/* /ad/leaderboard. /ad/live- /ad/load_ /ad/loading. /ad/log/* /ad/login- /ad/middle. /ad/mpu/* /ad/network/* /ad/omakasa. /ad/player| /ad/pong? /ad/popup. /ad/preview/* /ad/quigo/* /ad/random_ /ad/realclick. /ad/realclick/* /ad/rectangle. /ad/reklamy. /ad/request? /ad/right2. /ad/rotate? /ad/script/* /ad/select? /ad/serve. /ad/show. /ad/side_ /ad/skin_ /ad/skyscraper. /ad/skyscrapper. /ad/spacer. /ad/sponsored- /ad/sponsors/* /ad/status? /ad/superbanner. /ad/swf/* /ad/takeover/* /ad/textlinks/* /ad/timing. /ad/top. /ad/top/* /ad/top1. /ad/top2. /ad/top3. /ad/top_ /ad/view/* /ad0. /ad000/* /ad02/background_ /ad1-728- /ad1. /ad1/index. /ad12. /ad120x60. /ad125. /ad125b. /ad125x125. /ad132m. /ad132m/* /ad134m/* /ad136/* /ad15. /ad16. /ad160. /ad160k. /ad160x600. /ad1_ /ad1place. /ad1r. /ad1x1home. /ad2-728- /ad2. /ad2/index. /ad2/res/* /ad2010. /ad234. /ad24/* /ad247realmedia/* /ad290x60_ /ad2_ /ad2border. /ad2con. /ad2gate. /ad2gather. /ad2push. /ad2you/* /ad3. /ad300. /ad300f. /ad300f2. /ad300s. /ad300ws. /ad300x. /ad300x145. /ad300x250- /ad300x250. /ad300x250_ /ad350. /ad3_ima. /ad3i. /ad4. /ad41_ /ad468. /ad468x60. /ad468x80. /ad4i. /ad5. /ad6. /ad600x250. /ad600x330. /ad7. /ad728- /ad728. /ad728f. /ad728f2. /ad728s. /ad728t. /ad728w. /ad728ws. /ad728x. /ad728x15. /ad728x15_ /ad728x90. /ad8. /ad?channel= /ad?cid= /ad?count= /ad?currentview= /ad?iframe_ /ad?pos_ /ad?sponsor= /ad?type= /ad_120_ /ad_200x90_ /ad_234x60_ /ad_250x250_ /ad_300. /ad_300250. /ad_300_ /ad_600_ /ad_600x160_ /ad_728. /ad_728_ /ad_960x90_ /ad_agency/* /ad_area. /ad_art/* /Ad_Arub_ /ad_banner. /ad_banner/* /ad_banner1. /ad_banner2. /ad_banner_ /ad_bannerPool- /ad_banners/* /ad_bar_ /ad_base. /ad_big_ /ad_blog. /ad_bomb/* /ad_bot. /ad_bottom. /ad_box. /ad_box1. /ad_box2. /ad_box? /ad_box_ /ad_bsb. /ad_button. /ad_cache/* /ad_campaigns/* /ad_caption. /ad_check. /ad_choices. /ad_choices_ /ad_code. /ad_commonside. /ad_commonside_ /ad_configuration. /ad_configurations_ /ad_container_ /ad_content. /ad_contents/* /ad_count. /ad_counter. /ad_counter_ /ad_creatives. /ad_data/* /ad_detect. /ad_digital. /ad_dir/* /ad_display. /ad_display_ /ad_drivers/* /ad_ebound. /ad_editorials_ /ad_engine? /ad_entry_ /ad_feed. /ad_file/* /ad_files/* /ad_fill. /ad_filler. /ad_filmstrip/* /ad_flash/* /ad_flat_ /ad_floater. /ad_folder/* /ad_footer. /ad_footer_ /ad_forum_ /ad_frame. /ad_frame? /ad_frm. /ad_function. /ad_generator. /ad_generator? /ad_gif/* /ad_gif_ /ad_google. /ad_h.css? /ad_hcl_ /ad_hcr_ /ad_header. /ad_header_ /ad_height/* /ad_holder/* /ad_home2011_ /ad_home_ /ad_homepage_ /ad_horisontal. /ad_horiz. /ad_horizontal. /ad_html/* /ad_icons/* /ad_iframe. /ad_iframe_ /ad_image. /ad_image2. /ad_images/* /ad_img. /ad_img/* /ad_include. /ad_index_ /ad_insert. /ad_jnaught/* /ad_keywords. /ad_label2_ /ad_label728. /ad_label_ /ad_large. /ad_leader. /ad_leader_ /ad_leaderboard. /ad_leaderboard/* /ad_left. /ad_left_ /ad_legend_ /ad_link. /ad_links/* /ad_load. /ad_loader. /ad_loader2. /ad_locations/* /ad_log_ /ad_lomadee. /ad_manage. /ad_manager. /ad_manager/* /ad_master_ /ad_mbox. /ad_media/* /ad_medium_ /ad_mini_ /ad_mobile. /ad_mpu. /ad_multi_ /ad_navigbar_ /ad_news. /ad_note. /ad_notice. /ad_oas/* /ad_offersmail_ /ad_ops/* /ad_option_ /ad_overlay. /ad_page_ /ad_paper_ /ad_parts. /ad_peel/* /ad_pics/* /ad_pop. /ad_pop1. /ad_pos= /ad_position= /ad_position_ /ad_premium. /ad_premium_ /ad_preroll- /ad_print. /ad_rectangle_ /ad_refresh. /ad_refresher. /ad_reloader_ /ad_render_ /ad_renderv4_ /ad_rentangle. /ad_req. /ad_request. /ad_right. /ad_right_ /ad_rotation. /ad_rotator. /ad_rotator/* /ad_rotator_ /ad_script. /ad_script_ /ad_scroller. /ad_serv. /ad_serve. /ad_serve_ /ad_server. /ad_server/* /ad_servlet. /ad_shared/* /ad_show. /ad_show? /ad_side. /ad_sidebar/* /ad_sizes= /ad_skin_ /ad_sky. /ad_skyscraper. /ad_slideout. /ad_space. /ad_spot. /ad_square. /ad_square_ /ad_squares. /ad_srv. /ad_stem/* /ad_styling_ /ad_supertile/* /ad_sys/* /ad_syshome. /ad_system/* /ad_tab. /ad_tag. /ad_tag_ /ad_tags_ /ad_text. /ad_text_ /ad_tickets. /ad_tile/* /ad_timer. /ad_title_ /ad_top. /ad_top/* /ad_top_ /ad_topgray2. /ad_tower_ /ad_tpl. /ad_txt. /ad_units. /ad_units/* /ad_upload/* /ad_util. /ad_utils. /ad_utils/* /ad_ver/* /ad_vert. /ad_vertical. /ad_video.htm /ad_video1. /ad_view_ /ad_wide_ /ad_width/* /ad_wrapper. /ad_www_ /adactions. /adaffiliate_ /adanalytics. /adanim/* /adaptvadplayer. /adaptvadservervastvideo. /adaptvexchangevastvideo. /adarena/* /adasset/* /adasset4/* /adback. /adback? /adban. /adbanner. /adbanner/* /adbanner2. /adbanner_ /adbanners/* /adbar. /adbar/* /adbar2_ /adbar_ /adbars. /adbase. /adbeacon. /adbetween/* /adbg.jpg /adblob. /adblock.ash /adblock.js /adblock26. /adblock?id= /adblockl. /adblockr. /adbn? /adboost. /adborder. /adbot160. /adbot300. /adbot728. /adbot_ /adbotleft. /adbotright. /adbottom. /adbox. /adbox/* /adbox1. /adbox2. /adbox_ /adboxbk. /adboxes/* /adboxtable- /adbrite- /adbrite. /adbrite/* /adbrite2. /adbrite_ /adbriteinc. /adbriteincleft2. /adbriteincright. /adbucks/* /adbug_ /adbureau. /adbutler/* /adbytes. /adcache. /adcall. /adcalloverride. /adcampaigns/* /adcash- /adcash. /adcast01_ /adcast_ /adcde.js /adcdn. /adcell/* /adcenter.$script /adcentral. /adcframe. /adcgi? /adchain- /adchain. /adchannel_ /adcheck. /adcheck? /adchoice. /adchoice/* /adchoice_ /adchoices- /adchoices. /adchoices/* /adchoices16. /adchoices2. /adchoices_ /adchoicesfooter. /adchoicesicon. /adchoiceslogo. /adchoicesv4. /adcircle. /adclick. /adclick/* /adclient- /adclient. /adclient/* /adclix. /adclixad. /adclutter. /adcode. /adcode/* /adcode_ /adcodes/* /adcollector. /adcommon? /adcomp. /adcomponent/* /adconfig.js /adconfig.xml? /adconfig/* /adcontainer? /adcontent.$~object-subrequest /adcontent/* /adcontents_ /adcontrol. /adcontrol/* /adcontroller. /adcore. /adcore_ /adcount. /adcounter. /adcreative. /adcreative/* /adcss/* /adcycle. /adcycle/* /add728. /addata. /addatasandbox? /addeals/* /addefend. /addefend/* /addelivery/* /addeliverymodule/* /addisplay. /adds_banner/* /addyn/3.0/* /addyn|*;adtech; /addyn|*|adtech; /adedge/* /adengage- /adengage. /adengage/* /adengage0. /adengage1. /adengage2. /adengage3. /adengage4. /adengage5. /adengage6. /adengage_ /adengine/* /adengine_ /adentry. /aderlee_ads. /adError/* /adevent. /adevents. /adexample? /adexclude/* /adexternal. /adf.cgi? /adfactor/* /adfactor_ /adfactory- /adfactory. /adfactory_ /adfarm.$domain=~watchever.de /adfeed. /adfeedback/* /adfeedtestview. /adfetch. /adfetch? /adfetcher? /adfever_ /adfile. /adfile/* /adfiles. /adfiles/* /adfillers/* /adflash. /adflashes/* /adfly/* /adfolder/* /adfootcenter. /adfooter. /adFooterBG. /adfootleft. /adfootright. /adforgame160x600. /adforgame728x90. /adforgame728x90_ /adforge. /adformats/* /adforums/* /adfox. /adfr. /adframe. /adframe/* /adframe120. /adframe120x240. /adframe2. /adframe468. /adframe728a. /adframe728b. /adframe728b2. /adframe728bot. /adframe? /adframe_ /adframebottom. /adframecommon. /adframemiddle. /adframetop. /adframewrapper. /adfrequencycapping. /adfrm. /adfshow? /adfuncs. /adfunction. /adfunctions. /adgallery1. /adgallery1| /adgallery2. /adgallery2| /adgallery3. /adgallery3| /adgalleryheader. /adgear.js /adgearsegmentation. /adgenerator. /adgeo/* /adGet. /adgetter. /adgitize- /adgooglefull2. /adgraphics/* /adguard. /adguru. /adhads. /adhalfbanner. /adhandler. /adhandler/*$~subdocument /adhandlers- /adhandlers2. /adheader. /adheadertxt. /adheading_ /adhese. /adhese_ /adhints/* /adhomepage. /adhomepage2. /adhood. /adhost. /adhref. /adhtml/* /adhub. /adhug_ /adicon_ /adiframe. /adiframe/* /adiframe1. /adiframe18. /adiframe2. /adiframe7. /adiframe9. /adiframe? /adiframe_ /adiframeanchor. /adiframem1. /adiframem2. /adiframetop. /adiframe|*|adtech; /adify_ /adifyad. /adifyids. /adifyoverlay. /adim.html?ad /adimage. /adimage/* /adimage? /adimages. /adimages/*$~subdocument /adimg. /adimg/* /adinator/* /adinclude. /adinclude/* /adindex/* /adindicatortext. /adinit. /adinject. /adinjector. /adinjector_ /adinsert. /adinsertionplugin. /adinsertjuicy. /adinterax. /adiquity. /adiro. /adition. /adixs. /adj.php? /adjk. /adjs. /adjs/* /adjs_ /adjsmp. /adjug. /adjuggler? /adkeys. /adl.php /adlabel. /adlabel_ /adlabs.js /AdLanding. /adlandr. /adlantis. /adlantisloader. /adlargefooter. /adlargefooter2. /adlayer. /adlayer/* /adleader. /adleaderboardtop. /adleft. /adleft/* /adleftsidebar. /adlens- /adlesse. /adlift4. /adlift4_ /adline.$domain=~adline.co.il /adlink- /adlink. /adlink/* /adLink728. /adlink_ /adlinks. /adlinks2. /adlinks_ /adlist_ /adload. /adloader. /adlock300. /adlog.php? /adm/ad/* /admain. /admain| /adman. /adman/* /admanagement/* /admanagementadvanced. /admanager.$~object-subrequest /admanager/*$~object-subrequest /admanager3. /admanager_ /admanagers/* /admanagerstatus/* /admanproxy. /admantx- /admantx. /admantx/* /admarker. /admarker_ /admarket/* /admarvel. /admaster. /admaster? /admatch- /admatcher.$~object-subrequest,~xmlhttprequest /admatcherclient. /admatik. /admax.$domain=~admax.cn|~admax.co|~admax.eu|~admax.info|~admax.net|~admax.nu|~admax.org|~admax.se|~admax.us /admax/* /admaxads. /admeasure. /admedia. /admedia/* /admega. /admeld. /admeld/* /admeld_ /admeldscript. /admentor/* /admentor302/* /admentorasp/* /admentorserve. /admeta. /admez. /admez/* /admgr. /admicro2. /admicro_ /admin/ad_ /admin/banners/* /admin/sponsors/* /adminibanner2. /admixer_ /admob. /admonitor- /admonitor. /adnap/* /adNdsoft/* /adnet. /ADNet/* /adnet2. /adnetmedia. /adnetwork. /adnetwork/* /adnetwork300. /adnetwork468. /adnetwork_ /adnew2. /adnews. /AdNewsclip14. /AdNewsclip15. /adnext. /adnexus- /adng.html /adnl. /adnotice. /adobject. /adocean. /adometry- /adometry. /adometry? /adonline. /adonly468. /adops. /adops/* /adoptionicon. /adoptions. /adorika300. /adorika728. /ados.js /adotube_adapter. /adotubeplugin. /adoverlay. /adoverlay/* /adoverlayplugin. /adoverride. /adp-pro/* /adp.htm /adpage- /adpage. /adpage/* /adpagem. /adpages/* /adpan/* /adpanel/* /adpanelcontent. /adpartner. /adparts/* /adpatch. /adpeeps. /adpeeps/* /adperf_ /adperfdemo. /adphoto.$domain=~adphoto.fr /adpic. /adpic/* /adpicture. /adpicture1. /adpicture1| /adpicture2. /adpicture2| /adpictures/* /adping. /adplace/* /adplace5_ /adplacement. /adplay. /adplayer- /adplayer. /adplayer/* /adplugin. /adplugin_ /adpoint. /adpolestar/* /adpool/* /adpop. /adpopup. /adpositionsizein- /AdPostInjectAsync. /adprime. /adproducts/* /adprove_ /adprovider. /adproxy. /adproxy/* /adratio. /adrawdata/* /adreactor/* /adreadytractions. /adrec. /adrectanglebanner? /adrefresh- /adrefresh. /adrelated. /adreload. /adreload? /adremote. /adrendererfactory. /adreplace/* /adreplace160x600. /adreplace728x90. /adrequest. /adrequests. /adrequestvo. /adrequisitor- /adrevenue/* /adrevolver/* /adright. /adright/* /adrightcol. /adriver.$~object-subrequest /adriver/* /adriver_$~object-subrequest /adrobot. /adrolays. /adRoll. /adroller. /adrollpixel. /adroot/* /adrot. /adrot_ /adrotat. /adrotate- /adrotate. /adrotate/* /adrotation. /adrotator. /adrotator/* /adrotator2. /adrotv2. /adrun. /adruptive. /ads-01. /ads-02. /ads-03. /ads-04. /ads-05. /ads-06. /ads-07. /ads-1. /ads-2. /ads-250. /ads-300- /ads-300. /ads-admin. /ads-arc. /ads-banner /ads-blogs- /ads-common. /ads-foot. /ads-footer. /ads-header- /ads-holder. /ads-leader| /ads-min. /ads-new. /ads-nodep. /ads-pd. /ads-rectangle. /ads-rec| /ads-request. /ads-reviews- /ads-right. /ads-sa. /ads-scroller- /ads-segmentjs. /ads-service. /ads-skyscraper. /ads-sky| /ads-top. /Ads.ashx /ads.asp? /ads.aspx /ads.cfm? /ads.css /ads.dll/* /ads.gif /ads.htm /ads.js. /ads.js/* /ads.js? /ads.json? /ads.jsp /ads.pbs /ads.php /ads.pl? /ads.png /ads.swf /ads.v5.js /ads.w3c. /ads/125l. /ads/125r. /ads/160. /ads/160/* /ads/2.0/* /ads/2010/* /ads/250x120_ /ads/3.0/* /ads/300. /ads/3002. /ads/300x120_ /ads/468. /ads/468a. /ads/728. /ads/728b. /ads/?QAPS_ /ads/a. /ads/acctid= /ads/ad- /ads/ad. /ads/ad_ /Ads/adrp0. /ads/ads-$~stylesheet /ads/ads. /ads/ads/* /ads/ads_ /ads/adv/* /ads/afc/* /ads/aff- /ads/as_header. /ads/assets/* /ads/b/* /ads/banner- /ads/banner. /ads/banner/* /ads/banner01. /ads/banner_ /ads/banners/* /ads/beacon. /ads/behicon. /ads/bilar/* /Ads/Biz_ /ads/blank. /ads/bottom. /ads/box/* /ads/branding/* /ads/bt/* /ads/btbuckets/* /ads/center- /ads/center. /ads/click_ /ads/cnvideo/* /ads/common/* /ads/contextual. /ads/contextual_ /ads/contextuallinks/* /ads/create_ /ads/creatives/* /ads/cube- /ads/daily. /ads/daily_ /ads/dart. /ads/default_ /ads/design- /ads/dfp. /ads/dfp/* /ads/dhtml/* /ads/directory/* /ads/display/* /ads/displaytrust. /ads/empty. /ads/exit. /ads/fb- /ads/flash/* /ads/flash_ /ads/flashbanners/* /ads/footer- /ads/footer. /ads/footer_ /ads/freewheel/* /ads/g/* /ads/generatedHTML/* /ads/generator/* /ads/google1. /ads/google2. /ads/google_ /ads/gpt/* /ads/gpt_ /ads/header- /ads/header_ /ads/home/* /ads/homepage/* /ads/horizontal/* /ads/house/* /ads/house_ /ads/html/* /ads/htmlparser. /ads/iframe /ads/im2. /ads/image/* /ads/images/* /ads/imbox- /ads/img/* /ads/index- /ads/index. /ads/indexsponsors/* /ads/inline. /ads/inner_ /ads/interstitial. /ads/interstitial/* /ads/js. /ads/js/* /ads/js_ /ads/jsbannertext. /ads/labels/* /ads/layer. /ads/leaderboard- /ads/leaderboard. /ads/leaderboard/* /ads/leaderboard? /ads/leaderboard_ /ads/leaderbox. /ads/load. /ads/main. /ads/marketing/* /ads/masthead_ /ads/menu_ /ads/motherless. /ads/mpu/* /ads/mpu2? /ads/mpu? /ads/msn/* /ads/mt_ /ads/navbar/* /ads/ninemsn. /ads/oas- /ads/oas/* /ads/oas_ /ads/original/* /ads/oscar/* /ads/outbrain? /ads/overlay- /ads/overlay/* /ads/p/* /ads/page. /ads/panel. /ads/payload/* /ads/pencil/* /ads/player- /ads/plugs/* /ads/pop. /ads/popout. /ads/popshow. /ads/popup. /ads/popup_ /ads/post- /ads/postscribe. /ads/preloader/* /ads/preroll- /ads/preroll/* /ads/preroll_ /ads/promo_ /ads/proxy- /AdS/RAD. /ads/rail- /ads/rawstory_ /ads/real_ /ads/rect_ /ads/rectangle_ /ads/request. /ads/reskins/* /ads/right. /ads/right/* /ads/ringtone_ /ads/rotate/* /ads/rotate_ /ads/scriptinject. /ads/scripts/* /ads/select/* /ads/serveIt/* /ads/show. /ads/show/* /ads/side- /ads/sidebar- /ads/sidedoor/* /ads/sitewide_ /ads/skins/* /ads/sky_ /ads/spacer. /ads/sponsor /ads/square- /ads/square. /ads/square2. /ads/square3. /ads/storysponsors/* /ads/sub/* /ads/swfobject. /ads/takeovers/* /ads/third- /ads/tile- /ads/top- /ads/tracker/* /ads/triggers/* /ads/vertical/* /ads/vg/* /ads/video/* /ads/video_ /ads/view. /ads/views/* /ads/vip_ /ads/web/* /ads/webplayer. /ads/welcomescreen. /ads/widebanner. /ads/widget. /ads/writecapture. /ads/www/* /ads/xtcore. /ads/yahoo/* /ads/zone/* /ads0. /ads01. /ads05. /ads09a/* /ads1. /ads1/* /ads10. /ads10/* /ads100. /ads11. /ads11/* /ads12. /ads125. /ads125_ /ads160. /ads160x600- /ads160x600. /ads160x600px. /ads18. /ads2. /ads2/* /ads2012/* /ads2013/* /ads210. /ads2_ /ads2x300new. /ads3. /ads3/* /ads300. /ads300adn2. /ads300x250. /ads300X2502. /ads300x250_ /ads300x250px. /ads4.$domain=~ads4.city /ads4/* /ads468. /ads468x60. /ads468x60_ /ads5. /ads5/* /ads6. /ads6/* /ads600- /ads620x60/* /ads7. /ads7/* /ads728. /ads728adn2. /ads728x90_ /ads728x90a. /ads790. /ads8. /ads8/* /ads88. /ads9. /ads9/* /ads?apid /ads?id= /ads?spaceid /ads?zone= /ads?zone_id= /ads_1. /ads_160_ /ads_3. /ads_300. /ads_300_ /ads_6. /ads_728_ /ads_ad_ /ads_banner_ /ads_banners/* /ads_bg. /ads_bottom. /ads_bottom_ /ads_box_ /ads_code. /ads_code_ /ads_codes/* /ads_config. /ads_controller. /ads_display. /ads_event. /ads_files/* /ads_footer. /ads_frame. /ads_gallery/* /ads_global. /ads_gnm/* /ads_google. /ads_ifr. /ads_iframe. /ads_image/* /ads_images/* /ads_leaderboard_ /ads_left_ /ads_load/* /ads_loader. /ads_manager. /ads_medrec_ /ads_min_ /ads_new. /ads_new/* /ads_openx_ /ads_patron. /ads_php/* /ads_premium. /ads_pro/* /ads_r. /ads_reporting/* /ads_server_ /ads_show_ /ads_sidebar. /ads_start. /ads_text_ /ads_top_ /ads_ui. /ads_view. /ads_yahoo. /adsa468. /adsa728. /adsadclient31. /adsadview. /AdsAjaxRefresh. /adsales/* /adsame. /adsample. /adsandbox. /adsandtps/* /adsAPI. /adsatt. /adsbanner- /adsbanner. /adsbanner/* /adsbannerjs. /adsbox. /adsby. /adsbygoogle. /adscale. /adscale1. /adscale_ /adscalebigsize. /adscalecontentad. /adscaleskyscraper. /adscloud. /adscluster. /adscontent. /adscontent2. /adscript. /adscript1. /adscript_ /adscripts/* /adscripts1. /adscripts2. /adscripts3. /adscroll. /adsdaq_ /adsdaqbanner_ /adsdaqbox_ /adsdaqsky_ /adsdelivery. /adsdm. /adsdyn160x160. /adsDynLoad/* /adsearch. /adSearch? /adsecondary. /adsegmentation. /adseller/* /adsence. /adsenceSearch. /adsenceSearchTop. /adsEnd. /adsense- /adsense. /adsense/* /adsense1. /adsense2. /adsense23. /adsense24. /adsense250. /adsense3. /adsense4. /adsense5. /adsense? /adsense_ /AdsenseBlockView. /adsensegb. /adsensegoogle. /adsensets. /adsensev2. /adsenze. /adseo. /adseo/* /adseperator_ /adser/* /adserv. /adserv/* /adserv1. /adserv2. /adserv3. /adserv_ /adserve- /adserve. /adserve/* /adserve_ /adserver- /adserver. /adserver/* /adserver1- /adserver1. /adserver2. /adserver2/* /adserver3. /adserver7/* /adserver8strip. /adserver? /adserver_ /adserverdata. /adserverpub? /adservers- /adserversolutions/* /adserverstore. /adservervastvideovizu. /adservice- /adservice. /adservice/* /adservices/* /adservice| /adserving. /adserving/* /adserving_ /AdServlet? /adserv|*|adtech; /adsession. /adsession_ /adsetup. /adsetup_ /adsfac. /adsfetch. /adsfile. /adsfiles. /adsfinal. /adsfloat. /adsfolder/* /adsframe. /adsfuse- /adsgame. /adsGooglePP3. /adshandler. /adshare. /adshare/* /adshare3. /adsheader. /adshow- /adshow. /adshow/* /adshow? /adshow_ /adshtml2/* /adsi-j. /adsico. /adsico2. /adsico3. /adsicon/* /adsidebar. /adsidebarrect. /adsiframe. /adsiframe/* /adsign. /adsimage/* /adsimages/* /adsImg/* /adsinclude. /adsindie/* /adsinsert. /adsite/* /adsites/* /adsjs. /adskin/* /adsky. /adskyright. /adskyscraper. /adslide. /adslides. /adsline. /adslots. /adslug- /adslug_ /adslugs/* /adsm2. /adsmanagement/* /adsmanager/* /adsManagerV2. /adsmedia_ /adsmm.dll/* /adsmodules/* /adsnew. /adsnew/* /adsnip. /adsnippet. /adsniptrack. /adsonar. /adsopenx/* /adsource_ /adsoverlay_ /adsp/* /adspace. /adspace/* /adspace1. /AdSpace160x60. /adspace2. /adspace? /adspacer. /adspan. /adspeeler/* /adsplay. /adsponsor. /adspot. /adspot/* /adspot_ /adspots/* /adspro/* /AdsPublisher. /adsq/* /adsquare. /adsquareleft. /adsrc. /adsrc300. /adsremote. /adsreporting/* /adsresources/* /adsrich. /adsright. /adsrot. /adsrot2. /adsrotate. /adsrotate1left. /adsrotate1right. /adsrotate2left. /adsrotateheader. /AdsRotateNEW1right. /AdsRotateNEW2right. /AdsRotateNEWHeader. /adsrotator. /adsrule. /adsrules/* /adsrv. /adsrv/* /adsrv2/* /adss.asp /adsscript. /adsserv. /adsserver. /AdsShow. /adsshow/* /adssp. /adssrv. /adstacodaeu. /adstakeover. /adstatic. /adstatic/* /adstemplate/* /adstitle. /adstop. /adstop728. /adstop_ /adstorage. /adstracking. /adstract/* /adStrategies/* /adstream. /adstream_ /adstreamjscontroller. /adStrip. /adstrk. /adstrm/* /adstub. /adstube/* /adstubs/* /adstx. /adstyle. /adsummos. /adsummos2. /adsup. /adsvariables. /adsvo. /adsvr. /adswap- /adswap. /adswap/* /adswide. /adswidejs. /adsword. /adswrapper. /adswrapper3. /adswrapperintl. /adsx/* /adsx728. /adsx_728. /adsxml/* /adsync/* /adsyndication. /adsyndication/* /adsys. /adsys/* /adsystem. /adsystem/* /ads~adsize~ /adtable_ /adtadd1. /adtag. /adtag/* /adtag? /adtag_ /adtagcms. /adtaggingsubsec. /adtago. /adTagRequest. /adtags. /adtags/* /adtagtc. /adtagtranslator. /adtaily_ /adtaobao. /adtech- /adtech. /adtech/* /adtech; /adtech_ /adtechglobalsettings.js /adtechHeader. /adtechscript. /adtest. /adtest/* /adtext. /adtext2. /adtext4. /adtext_ /adtextmpu2. /adtimage. /adtitle. /adtology. /adtomo/* /adtonomy. /adtool/* /adtools/* /adtools2. /adtooltip/* /adtop. /adtop160. /adtop300. /adtop728. /adtopcenter. /adtopleft. /adtopmidsky. /adtopright. /adtopsky. /adtrack. /adtrack/* /adtracker. /adtracker/* /adtracker? /adtracking. /adtracking/* /adtraff. /adttext- /adttext. /adtvideo. /adtxt. /adtype. /adtype= /adultadworldpop_ /adultimate. /adunit. /adunit/* /adunits. /adunits/* /adunits? /adunittop| /adunix. /adutil. /adutils. /aduxads. /aduxads/* /adv-1. /adv-2. /adv-banner. /adv-banners/* /adv-div- /adv-expand/* /adv-ext- /adv-f. /adv-scroll. /adv-socialbar- /adv.asp /adv.css? /adv.html /adv.jsp /adv.php /adv.png /adv/adriver /adv/ads/* /adv/adv. /adv/adv_ /adv/background/* /adv/banner/* /adv/banner1/* /adv/bottomBanners. /adv/box- /adv/kelkoo/* /adv/kelkoo_ /adv/lrec_ /adv/managers/* /adv/mjx. /adv/mobile/* /adv/preroll_ /adv/rdb. /adv/script1. /adv/script2. /adv/search. /adv/skin. /adv/skin_ /adv/sponsor/* /adv/sprintf- /adv/topBanners. /adv02. /adv03. /adv1. /Adv150. /adv2. /adv3. /adv4. /Adv468. /adv5. /adv6. /adv8. /adv_2. /adv_468. /adv_background/* /adv_banner_ /adv_box_ /adv_burt_ /adv_flash. /adv_frame/* /adv_horiz. /adv_image/* /adv_left_ /adv_library3. /adv_link. /adv_manager_ /adv_player_ /adv_script_ /adv_server. /adv_top. /adv_vert. /adv_vertical. /advalue/* /advalue_ /advaluewriter. /advault. /advbanner/* /advcontents. /advcounter. /advdoc/* /advengine. /adver-left. /adver. /adver_hor. /adverfisement. /adverfisement2. /adverserve. /advert- /advert. /advert/* /advert01. /advert1. /advert1/* /advert2. /advert3. /advert31. /advert32. /advert33. /advert34. /advert35. /advert36. /advert37. /advert4. /advert5. /advert6. /advert? /advert_ /advertbanner. /advertbanner2. /advertbox. /advertguruonline1. /adverth. /adverthorisontalfullwidth. /advertical. /advertise- /advertise.$domain=~advertise.bingads.microsoft.com /advertise/* /advertise125x125. /advertise_ /advertisehere. /advertisement- /advertisement. /advertisement/* /advertisement1. /advertisement160. /advertisement2. /advertisement3. /advertisement_ /advertisementheader. /advertisementmapping. /advertisementrotation. /advertisements- /advertisements. /advertisements/* /advertisements2. /advertisements_ /AdvertisementShare. /advertisementview/* /advertiser.$domain=~advertiser.growmobile.com /advertiser/*$domain=~bingads.microsoft.com|~mobileapptracking.com|~trialpay.com /advertisers.$image,script,subdocument /advertisers/* /advertiserwidget. /advertises/* /advertisewithus_ /advertising-$domain=~outbrain.com /advertising. /advertising/*$~xmlhttprequest,domain=~temple.edu /advertising02. /advertising2. /advertising300x250. /advertising? /advertising_ /advertisingbanner. /advertisingbanner/* /advertisingbanner1. /advertisingbanner_ /advertisingcontent/* /AdvertisingIsPresent6? /advertisinglinks_ /advertisingmanual. /advertisingmodule. /advertisings. /advertisingwidgets/* /advertisment- /advertisment. /advertisment/* /advertisment1- /advertisment_ /advertisments/* /advertize_ /advertlayer. /advertmedia/* /advertmsig. /advertorial/* /advertorial_ /advertorials/* /advertphp/* /advertpixelmedia1. /advertpro/* /advertrail. /advertright. /adverts. /adverts/* /adverts_ /advertserve. /advertsky. /advertsquare. /advertstub. /advertverticallong. /advertwebapp. /advf1. /advfiles/* /advhd. /advice-ads. /adview. /adview/* /adview? /adview_ /adviewas3. /adviewed. /adviewer. /adviframe/* /advinfo. /advision. /adVisit. /advlink300. /advloader. /advolatility. /advpartnerinit. /advPop. /advpreload. /advris/* /advrotator. /advs.ads. /advs/* /advscript. /advscripts/* /advshow. /advt. /advt/* /advt2. /advtemplate/* /advtemplate_ /advweb. /advzones/* /adw.shtml /adw2.shtml /adweb. /adweb2. /adwidgets/* /adwise/* /adWiseShopPlus1. /adwiz. /adwiz/* /adwizard. /adwizard_ /adwolf. /adwords.$domain=~ppc.ee /adwords/* /adwordstracking.js /adWorking/* /adworks.$domain=~adworks.co.il /adworks/* /adworldmedia/* /adworx. /adworx_ /adwrapper/* /adwrapperiframe. /adwriter2. /adx. /adx/ads? /adx160. /adx2. /adx_exo_ /adx_flash. /adx_iframe_ /adxsite. /adxx.php? /adyard. /adyard300. /adyea. /adzbotm. /adzerk2_ /adzone. /adzone/* /adzone4. /adzone_ /AdZoneAdXp. /adzonebelowplayer. /adzonebottom. /adzonecenteradhomepage. /adzoneleft. /adzonelegend. /adzoneplayerright. /adzoneright. /adzones/* /adzonesidead. /adzonetop. /adztop. /afc-match?q= /afcads. /afcsearchads. /afdsafads/* /aff-exchange/* /aff.htm /aff/ads_ /aff/images/* /aff_ad? /aff_banners/* /aff_frame. /affad? /affads/* /affbanner/* /affbanners/* /affbeat/banners/* /affclick/* /affilatebanner. /affiliate-content/* /affiliate/ad/* /affiliate/ads/* /affiliate/banner/* /affiliate/banners/* /affiliate/promo- /affiliate/promo/* /affiliate/script.php? /affiliate/small_banner/* /affiliate_banner/* /affiliate_banners/* /affiliate_base/banners/* /affiliate_resources/* /affiliate_show_banner. /affiliate_show_iframe. /affiliateads/* /affiliateadvertisement. /affiliatebanner/* /affiliatebanners/* /affiliateimages/* /affiliates.*.aspx? /affiliates/*/show_banner. /affiliates/ban /affiliates/contextual. /affiliatetags/* /affiliatewiz/* /affiliation/* /affiliationcash. /affilinet/* /affilitebanners/* /affimages/* /affimg/* /affliate-banners/* /affpic/* /afr.php? /afr?auid= /ahmestatic/ads/* /ajax-ad/* /ajax-advert- /ajax-advert. /ajax/ad/* /ajax/ads/* /ajaxAd? /ajaxads. /ajrotator/* /ajs.php? /ajs?auid= /ak/ads/* /all/ad/* /all_ads/* /alternet.ad? /alwebad_ /am/ads. /amazon/iframeproxy- /amazon/widget/* /amzn_omakase. /anchorad. /annonse. /annonse/* /annonser. /annonser/* /announce/adv/* /anyad.js /api.ad. /api/ad/* /api/ads/* /apopwin. /app.ads- /app.ads. /app/ads. /app/ads/* /aptads/* /Article-Ad- /article_ad. /articleSponsorDeriv_ /artimediatargetads. /as3overstreamplatformadapter. /as_u/ads/* /aseadnshow. /aspbanner_inc.asp? /asset/ad/* /asset/adv/* /assets/ad- /assets/ad/* /assets/ads- /assets/ads/* /assets/ads_ /assets/adv/* /assets/doubleclick/* /ast/ads/* /athena/tag/? /atnads/* /AttractiveAds/* /AttractiveAds_ /AttractiveAdsCube. /au2m8_preloader/* /audio-ads/* /audioads/* /auditudeadunit. /auditudebanners. /austria_ad. /auto_ad_ /awe2.js /awempire. /awepop. /b.ads. /back-ad. /background_ad_ /BackgroundAd40. /backgroundAdvertising. /backlinxxx/js/* /badge_ad_ /ban.php? /ban160.php /ban300.html /ban300.php /ban728.html /ban728.php /ban728x90. /ban_ad. /ban_m.php? /banimpress. /banman.asp? /banman/* /banmanpro/* /Banner-300x250. /banner-ad- /banner-ad. /banner-ad/* /banner-ad_ /banner-ads/* /banner.asp?$third-party /banner.ca? /banner.cgi? /banner.gif? /banner.htm? /banner.php /banner.ws? /banner/468 /banner/700 /banner/ad. /banner/ad/* /banner/ad_ /banner/adv/* /banner/adv_ /banner/affiliate/* /banner/rtads/* /banner/sponsor_ /banner/virtuagirl /banner160x600- /banner20468x60. /banner460x80. /banner468. /banner468_ /banner468a. /banner468x60. /banner468x80. /banner728x90_ /banner_125x /banner_468. /banner_468x /banner_ad. /banner_ad_ /banner_ads. /banner_ads/* /banner_ads_ /banner_adv/* /banner_control.php? /banner_db.php? /banner_file.php? /banner_iframe_ /banner_image.php? /banner_js.*? /banner_OAS.js /banner_skyscraper. /banner_view. /banner_zanox/* /banner_zedo/* /bannerad. /bannerad/* /bannerad1- /bannerad2- /bannerad3. /bannerad6. /bannerad_ /bannerads- /bannerads. /bannerads/* /banneradsajax. /banneradsgenerator. /banneradverts/* /banneradviva. /bannercode.php /bannerconduit. /bannerexchange/* /bannerfarm. /bannerfarm/* /bannerfile/ad_ /bannerframe.*? /bannerframeopenads. /bannerframeopenads_ /bannerinc. /bannerjs.php? /bannermaker/* /bannermanager/* /bannermvt. /bannerpump. /bannerrotate. /bannerrotater/* /bannerrotation. /bannerrotation/* /banners.*&iframe= /banners.cgi? /banners.php?id /banners/160 /banners/300 /banners/460 /banners/468 /banners/728 /banners/ad/* /banners/ad10. /banners/ad11. /banners/ad_ /banners/ads- /banners/ads. /banners/ads/* /banners/adv/* /banners/adv_ /banners/aff. /banners/affil/* /banners/affiliate/* /banners/ffadult/* /banners/googlebanner /banners/promo/* /banners_rotation. /bannersAds_ /bannerscript/* /bannerserve/* /bannerserver/* /bannerserver3/* /bannerserver3| /bannerserver? /bannersyndication. /bannerview.*? /bannerwerbung/* /bannery/*?banner= /bansrc/* /bar-ad. /baseAd. /baselinead. /basic/ad/* /bbad. /bbad1. /bbad10. /bbad2. /bbad3. /bbad4. /bbad5. /bbad6. /bbad7. /bbad8. /bbad9. /bckgrnd_ad. /bdcustomadsense- /beacon/ad/* /behaviorads/* /beta-ad. /betrad.js /bftv/ads/* /bg-advert- /bg/ads/* /bg_ads_ /bgads/* /bi_affiliate.js /bigad. /bigad_ /bigads/* /bigboxad. /bigtopl.swf /bin/ads/* /binary/ad/* /bizad. /bkgrndads/* /blockad_ /blocks/ads/* /blog-ad- /blog/ads/* /blog_ad? /blog_ads/* /blogad. /blogad02. /blogad_ /blogads- /blogads. /blogads/* /blogads2_ /blogads3/* /blogads_ /blogadsbg. /bloggerex. /blogoas- /bmndoubleclickad. /bnr.php? /bnr_show.php?id=$script /bnrad/* /bnrimg. /bnrsrv. /bodyads/* /bookad/* /bookads. /bookads2. /boomad. /bottom-ad- /bottom-ads. /bottom-advert- /bottom_ad. /bottom_ads. /bottom_adv. /bottom_adv_ /bottomad. /bottomad/* /bottomads. /bottomsidead/* /box_ad_ /box_ads_ /boxad. /boxad1. /boxad2. /boxad3. /boxad_ /breakad_ /brightcovead. /bserver/* /btbuckets/btb.js /btmads. /btmadsx. /btn_ad_ /bucketads. /buddyw_ad. /burt/adv_ /butler.php?type= /button_ads/* /buttonad/* /buttonads. /buttonads/* /buyad. /buyclicks/* /buyer/dyad/* /buysellads- /buysellads. /buzz/ads/* /bytemark_ad. /cache/ads_ /cads-min.js /calendar-ads/* /call/pubif/* /call/pubj/* /call_ads/* /callads5. /callAdserver? /camaoadsense. /camaoAdsenseHomepage. /camfuzeads/* /campus/ads/* /carbonads- /carbonads/* /carsadtaggenerator.js /cashad. /cashad2. /category-sponsorship/* /catfishads/* /cb.php?sub$script,third-party /cci-ads- /cdn-cgi/pe/bag?r[]=*cpalead.com /cdn.ads. /centerads. /central/ads/* /ceoads/* /cgi-bin/ad/* /cgi-bin/ads. /cgi-bin/ads/* /cgi-bin/ads_ /cgi-exe/ad. /cgi/ad_ /channelblockads. /checkm8footer_ /checkm8header_ /chinaadclient. /chitika-ad? /chrome-ad. /ciaad. /circads. /cjadsprite. /ck.php?nids /clarityray.js /ClassAds/* /classifieds/banners/* /click/ads_ /clickboothad. /clicksor. /clickunder. /clients/ads/* /clkads. /cm/ads/* /cms/ads/* /cms/js/ad_ /cn-advert. /cnads.js /cnnslads. /cnxad- /codaadconfig. /coldseal_ad. /collisionadmarker. /colorscheme/ads/* /columnadcounter. /columnads/* /com/ads/* /combo?darla/* /comment-ad- /comment-ad. /commercial_horizontal. /commercial_top. /common-ads/* /common/ad. /common/ad/* /common/ad_ /common/ads/* /common/adv_ /common/dart_wrapper_ /common_ad. /commons/ad/* /commspace_ad. /companion_ad. /companion_ads. /companionAdFunc. /compban.html? /components/ads/* /conad. /conad_ /configspace/ads/* /cont-adv. /contads. /contaxe_ /content-ads. /content/ad/* /content/ad_ /content/ads/* /content/adv/* /content_ad. /content_ad_ /contentAd. /contentad/* /contentad_ /contentAdServlet? /contentadvert1. /contentadxxl. /contentad| /context_ad/* /context_ads. /contextad. /contextads. /contextualad. /contpop.js| /contribute_ad. /controller/ads/* /controllerimg/adv/* /convertjsontoad. /core-ads- /core/ad/* /core/ads/* /coread/* /corner-ad. /corner_ads/* /cornerbig.swf /cornersmall.swf /country_ad. /coxads/* /cpm160. /cpm728. /cpm_ad. /cpmbanner. /cpmcampaigns/* /cpmrect. /cpx-ad. /cpx_ads. /cpxads. /cramitin/ads_ /criteo. /Criteo/* /criteo_ /criteoRTA. /crossoverad- /csp/ads? /css/ad. /css/ads. /css/adsense /css/adv. /cssjs/ads/* /ctamlive160x160. /cube_ads/* /cubead. /cubeads/* /cubeads_ /curlad. /curveball/ads/* /custads/* /custom/ads /custom/doubleclick/* /custom11x5ad. /custom_ads/* /customad. /customadmode. /customads/* /customadsense. /customcontrols/ads/* /customerad_ /cutead. /cvs/ads/* /cwggoogleadshow. /d/ads/* /daily/ads/* /dart_ads. /dart_ads/* /dart_enhancements/* /dartad/* /dartadengine. /dartadengine2. /dartads. /dartcall. /dartfunctions. /data/ads/* /dateads. /dblclick. /dblclickad. /dclk/dfp/* /dclk_ads. /dclk_ads_ /dcloadads/* /ddlads/* /de/ads/* /default-adv/* /default/ads/* /default_ads/* /default_adv. /default_oas. /defaultad? /defaults_ads/* /defer_ads. /deferads. /defersds. /delayedad. /deliver.jphp? /deliver.nmi? /deliverad/* /deliverads. /deliverjs.nmi? /deliversd/* /deliversds. /delivery.ads. /delivery.php?pool_id= /delivery.php?rnd= /delivery/*?advplaces= /delivery/afr. /delivery/ag. /delivery/al.php /delivery/apu.php /delivery/avw. /delivery/fc. /delivery/fl. /delivery/lg. /delivery/spc. /delivery/vbafr.php /delivery_ads/* /demo/ads/* /DemoAd. /descpopup.js /design/ads/* /develop/ads_ /devicead/* /dfp/dc.js /dfpads. /dfpsds. /dfpsearchads. /dictionary/ads/* /dif/?cid /dig_ad. /digest/ads. /digg_ads. /digg_ads_ /dinclinx.com/* /direct_ads. /directads. /directadvert. /directrev. /discuss_ad/* /DispAd_ /display-ad/* /display-ads- /display-ads/* /display.ad. /display?ad_ /display_ad /displayad. /displayad/* /displayad? /displayadbanner_ /displayadiframe. /displayadleader. /displayads. /displayads/* /displayads1. /displayads2. /displayads3. /displayadsiframe. /div-ads. /divad/* /dlfeatads. /dmn-advert. /dne_ad. /dns_ad/* /dnsads. /domainads/* /doodads/* /door/ads/* /doors/ads/* /doubleclick.aspx /doubleclick.js /doubleclick.php /doubleclick.swf /doubleclick/iframe. /doubleclick_ads. /doubleclick_ads/* /doubleclickad. /doubleclickads? /doubleclickbannerad? /doubleclickcontainer. /doubleclickinstreamad. /doubleclickloader. /doubleclickplugin. /doubleclicktag. /doublepimp2.js /downads. /download/ad. /download/ad/* /download/ads /drawad. /driveragentad1. /driveragentad2. /drivingrevenue/* /droelf.kit/a/* /dropdown_ad. /dsg/bnn/* /dspads. /dtiadvert125x125. /dtim300x250.$script /dtmads/* /dxd/ads/* /dyn_banner. /dyn_banners_ /dynamic-ad- /dynamic/ads/* /dynamic_ads/* /DynamicAd/* /dynamicad? /dynamiccsad? /dynamicvideoad? /dynanews/ad- /dynbanner/flash/* /e-vertising/* /eas-fif.htm /eas?*^easformat= /eas?camp=*;cre= /eas?cu=*;cre= /eas?cu=*;ord= /eas_fif. /eas_tag.1.0.js /easyads. /easyads/* /easyadstrack. /easyazon- /ebay_ads/* /ebayad. /eco_ads/* /ecom/magnet. /editable/ads/* /emailads/* /embed_ad. /emediatead. /EmreAds. /ems/ads. /en/ads/* /eng/ads/* /eporner-banner- /ept_in.php? /ero-1. /ero-ads- /ero-ads_ /ero-advertising. /ero.htm /ero_hosted_ /ero_line_ /eroad.php /eroad2. /eroads. /eroadvertising. /eroadvertorial2. /eroadvertorial3. /erobanner. /eroex. /eros.htm /eshopoffer. /esi/ads/* /etology.$domain=~etology.com /euads/* /event.ng/* /excellence/ads/* /exchange_banner_ /exit_popup /exitpop. /exitpopunder. /exitpopunder_ /exitpopup. /exitsplash. /exo120x60. /exobanner. /exoclick. /exoclickright. /exoclickright1. /exoclickright2. /exoclickright3. /expandable_ad.php /expandable_ad? /expandingads. /expandy-ads. /expop.js /exports/tour/*$third-party /exports/tour_20/* /ext/ads/* /ext_ads. /extadv/* /extendedadvert. /external/ad. /external/ad/* /external/ads/* /external_ads. /externalad. /ExternalAdNetworkViewlogLogServlet? /externalads/* /externalhtmladrenderer. /eyewondermanagement. /eyewondermanagement28. /facebookaff/* /facebookaff2/* /facebooksex. /fan-ads.$script /fastclick160. /fastclick728. /fatads. /fbads/* /fc_ads. /fea_ads. /featuredadshome. /feedads. /file/ad. /files/ad- /files/ad/* /files/ads- /files/ads/* /filter.php?pro$script /fimserve. /finads. /first-ad_ /flag_ads. /flash-ads. /flash-ads/* /flash/ad/* /flash/ad_ /flash/ads/* /flash/advertis /flash_ads. /flashad. /flashad3. /flashads. /flashads/* /flashpeelads/* /flatad. /flesh_banner /fleshlight. /fleshlightcash_ /fliionosadcapture- /flirt4free. /float-ads/* /float_ad. /floatad_ /floatads. /floatadv. /floater_ad. /floatingad. /FloatingAd_ /floatingads. /floaty_rotator /flv-ad- /flvad_ /flvads/* /flyad/* /flyads/* /flyers/ads/* /fn_ads. /footad- /footad. /footer-ad- /footer-ad. /footer-ads/* /footer_ad. /footer_ad_ /footer_ads. /footerad. /footerad? /footerads. /footerads/* /footertextads. /forads. /forum/ads/* /forums/ad/* /frame_ads_ /framead- /framead. /framead/* /framead_ /frameads. /frameads1. /frameads_ /frameadsz. /freead. /freead2. /frequencyads. /friendfinder_ /frnads. /frontend/ads/* /frontpagead/* /ftp/adv/* /full/ads/* /fullad. /fulladbazee. /fuseads/* /fwadmanager. /gadgets/ad/* /gads.html /gads.js /gafc.js /gafsads? /gafv_adapter. /galleryad. /gam.html? /gam_ad. /gam_ad_ /gam_ads. /gamads/* /game-ads. /gamead/* /gameadsync. /gamersad. /GAN_Ads/* /gannett/ads/* /gate-ad- /gatewayAds. /gazette/ads/* /geitonpop. /gen_ads_ /genads/* /general-ad- /general/ads /generate_ad. /generate_ads. /generateadtag. /generateplayerads. /genericrichmediabannerad/* /geo-ads_ /geo/ads. /geo_banner.htm? /geoad/* /geobox.html /GeoDynBanner.php?wmid= /ges_ads/* /get-ad. /get-advert- /get.ad? /get/ad. /get/ad/* /get/ad? /get_ad_ /get_ads. /get_ads/* /get_banner.asp? /getad. /getad? /getadcontent. /getadds. /GetAdForCallBack? /getadframe. /getads- /getads. /getads/* /getads? /getadserver. /getadsettingsjs? /getads| /getadvertimageservlet? /getAdvertisement^ /getadvertiserimage. /getadverts? /GetADVOverlay. /getarticleadvertimageservlet? /getban.php? /getbanner.cfm? /getbanner.php? /getdigitalad/* /getfeaturedadsforshow. /gethalfpagead. /getinlineads/* /getJsonAds? /getmarketplaceads. /getmdhlayer. /getmdhlink. /getmyad/* /getrcmd.js? /getsad.php? /getsponslinks. /getsponslinksauto. /getTextAD. /GetVASTAd? /getvdopiaads. /getvideoad. /getwebsitead/* /gexternalad. /gfx/ad/* /gfx/ads/* /ggadsense. /gifs/ads/* /glam160. /glam300. /glam728. /glam_ads. /global-ads_ /global/ad/* /global/ads. /global/ads/* /globalad. /globaladprostyles. /globalbannerad. /googad300by600. /google-ad- /google-ad? /google-ads. /google-ads/* /google-adsense- /google-adsense. /google-adverts- /google-adwords /google-afc- /google-afc. /google/ad? /google/adv. /google160. /google728. /google_ad. /google_ad_ /google_ads. /google_ads/* /google_ads_ /google_adv/* /google_afc. /google_afc_ /google_afs. /google_afs_widget/* /google_caf.js? /google_lander2.js /google_radlinks_ /googlead- /googlead. /googlead1. /googlead160. /GoogleAd300. /googlead336x280. /googlead_ /GoogleAdBg. /googleadcode. /googleaddfooter. /googleaddisplayframe. /googleadhp. /googleadhpbot. /googleadhtml/* /googleadiframe_ /googleadright. /googleads- /googleads. /googleads/* /googleads1. /googleads2. /googleads3widetext. /googleads_ /googleadsafc_ /googleadsafs_ /googleAdScripts. /googleadsense. /googleAdTaggingSubSec. /googleadunit? /googleafc. /googleafs. /googleafvadrenderer. /googlecontextualads. /googleheadad. /googleleader. /googleleads. /googlempu. /gpt_ads- /graphics/ad_ /graphics/ads/* /grid-ad. /groupon/ads/* /gt6skyadtop. /guardianleader. /guardrailad_ /gujAd. /hads- /Handlers/Ads. /hcm_ads/* /hdadvertisment- /header-ad. /header_ad_ /header_ads_ /headerad. /headeradd2. /headerads. /headerads1. /headerAdvertismentTab. /headermktgpromoads. /headvert. /hiadone_ /hikaku/banner/* /hitbar_ad_ /holl_ad. /home/_ads /home/ad_ /home/ads- /home/ads/* /home/ads_ /home/sponsor_ /home30/ad. /home_adv. /homeoutside/ads/* /homepage/ads/* /homepage_ad_ /homepage_ads/*$domain=~swedishbeauty.com /homepageadvertright. /homeslideadtop/* /HomeStaticAds/* /horizontal_advert_ /horizontalAd. /hostedads. /hostedbannerads. /hostgator-ad. /hosting/ads/* /hostkey-ad. /house-ad. /house-ad/* /house-ads/* /house_ad- /house_ad_ /house_ads/* /housead. /housead/* /housead_ /houseads. /houseads/* /houseads? /hoverad. /hpcwire/ads/* /html.ng/* /html/ad. /html/ad/* /html/ads/* /html/ads_ /html/sponsors/* /htmlads/* /httpads/* /hubxt.*/js/eht.js? /hubxt.*/js/ht.js /i/ads/* /i_ads. /ia/ads/* /iabadvertisingplugin.swf /IBNjspopunder. /icon_ad. /icon_ads_ /icon_advertising_ /idevaffiliate/* /ifolder-ads. /iframe-ad. /iframe-ads/* /iframe-mgid- /iframe.ad/* /iframe/ad/* /iframe/ad_ /iframe/ads/* /iframe_ad. /iframe_ad? /iframe_ad_ /iframe_ads/* /iframe_ads_ /iframe_chitika_ /iframe_sponsor_ /iframead. /iframead/* /iframead_ /iframeadcontent. /iframeads. /iframeads/* /iframeadsense. /iframeadsensewrapper. /iframedartad. /iframes/ad/* /ifrm_ads/* /ignite.partnerembed.js /ignitecampaigns.com/* /ilivid-ad- /im-ad/im-rotator. /im-ad/im-rotator2. /im-popup/* /im.cams. /ima/ads_ /imaads. /imads.js /image/ad/* /image/ads/* /image/ads_ /image/adv/* /image/affiliate/* /image_ads/* /imageads/* /imagecache_ads/* /images-ad/* /images-v2/ad_ /images.ads. /images.adv/* /images/ad- /images/ad.$domain=~ngohq.com /images/ad/* /images/ad2/* /images/adds/* /images/ads- /images/ads. /images/ads/* /images/ads_ /images/adv- /images/adv. /images/adv/* /images/adv_ /images/adver- /images/aff- /images/affs/* /images/awebanner /images/bg_ad/* /images/gads_ /images/livejasmin/* /images/sponsored. /images/sponsored/* /images/vghd /images1/ad_ /images2/ads/* /images_ad/* /images_ads/* /imagesadspro/* /imfloat. /img-ads/* /img.ads. /img/_ad. /img/ad- /img/ad. /img/ad/* /img/ad_ /img/ads/* /img/adv. /img/adv/* /img2/ad/* /img3/ads/* /img_ad/* /img_ad_ /img_ads/* /img_adv/* /imgad. /imgad? /imgad_ /imgAdITN. /imgads/* /imgaffl/* /imgs/ad/* /imgs/ads/* /imlive.gif /imlive300_ /imlive5. /imp.ads/* /impop. /impopup/* /inad. /inc/ad- /inc/ad. /inc/ads/* /inc_ad. /inc_ad_ /inc_ads. /inc_v2/ad_ /include/ad/* /include/ad_ /include/ads/* /include/adsdaq /included_ads/* /includes/ad. /includes/ad_ /includes/ads/* /includes/ads_ /incmpuad. /index-ad- /index-ad. /index_ads. /inhouse_ads/* /initdefineads. /initlayeredwelcomead- /injectad. /INjspopunder. /inline_ad. /inline_ad_ /inline_ads. /inlineads/* /inlinetextads? /inner-ads- /inner-ads/* /innerads. /inquirer/ads/* /insertads. /instreamad/* /intelliad. /intellitext. /interad. /internAds. /internal-ad- /internet_ad_ /internetad/* /interstitial-ad. /interstitial-ad/* /interstitial_ad. /intextadd/* /intextads. /introduction_ad. /inv/ads/* /inventory/ad/* /invideoad. /inviteads/* /inx-ad. /ip-advertising/* /ipadad. /iprom-ad/* /iqadcontroller. /irc_ad_ /ireel/ad*.jpg /is.php?ipua_id=*&search_id= /iserver/ccid= /iserver/site= /isgadvertisement/* /ispy/ads/* /iwadsense. /j/ads.js /jamnboad. /javascript/ads. /javascript/ads/* /javascript/oas. /javascript/oas? /javascripts/ads/* /jcorner.php?partner= /jitads. /jivoxadplayer. /jlist-affiliates/* /JPlayerAdFoxAdvertisementPlugin. /jqads. /jquery-ads. /jquery.adx. /jquery/ad. /jqueryadvertising. /js.ad/size= /js.ng/cat= /js.ng/channel_ /js.ng/pagepos= /js.ng/site= /js.ng/size= /js/ads- /js/ads. /js/ads_ /js/adv. /js/adv/* /js/doubleclick/* /js/oas- /js/oas. /js/ppu.$script /js/youmuffpu.js /js2.ad/size= /js_ad_utf8. /js_ads/* /js_ads_ /js_adv_ /jsad.php /jsad/* /jsads- /jsAds/* /jsadscripts/* /jsc/ads. /jsfiles/ads/* /json/ad/* /jsplayerads- /jspopunder. /jstextad. /jsVideoPopAd. /jtcashbanners/* /juicyads_ /jumpstartunpaidad. /kaksvpopup. /KalahariAds. /kampyle.js /kantarmedia. /keyade.js /keyword_ad. /kredit-ad. /kskads. /landerbanners/* /landingadvertisements/* /large_ads/* /layad. /layer-ad. /layer-ads. /layer-advert- /layer.php?bid= /layer/ad. /layer/ads. /layer160x600. /layer_ad? /layerad- /layerad. /layerAd/* /layerads- /layerads. /layerads_ /layout.inc.php?img /layout/ad. /layout/ads/* /lazyad. /lbl_ad. /leadads/* /leader_ad. /leaderad. /leaderboard-advert. /leaderboard_ad/* /leaderboard_adv/* /leaderboardad. /leaderboardadblock. /leaderboardads. /ledad. /left-ads. /left_ad_ /left_ads. /leftad. /leftad_ /leftads. /leftbanner/* /leftsidebarads. /lib/ad.js /library/ads/* /lifeshowad/* /lightad. /lightboxad^ /lightboxbannerad^ /lijit-ad- /lijitads. /linkad2. /linkads. /linkadv. /linkadv_ /linkedads/* /links_sponsored_ /live_ad. /liveads. /livejasmin. /livejasmin/*&id= /livejasmin2. /livejasmin_ /livejasmine03. /livejasmine05. /load-ads| /load_ad? /loadad.aspx? /loadads. /loadads/* /loadadsmain. /loadadsmainparam. /loadadsparam. /loadadwiz. /loading_ads. /local_ads_ /localAd/* /LocalAd_ /localAdData/* /LocalAdNet/* /localads. /localcom-ad- /locker.php?pub=*&gateid=$script /log_ad? /log_ad_ /logad? /logo-ads. /logoads. /logoutad. /lotto_ad_ /lrec_ad. /m0ar_ads. /mac-ad? /mad.aspx? /mad_ad. /magazine/ads. /magic-ad/* /magic-ads/* /main/ad_ /main/ads/* /main_ad. /main_ad/* /mainad. /mainpagepopupadv1. /mapquest/Ads/* /marginaleadservlet? /marketing-banners/* /marketing/banners/* /marketing/banners_ /markpop.js /masonad.gif /masterad. /match_ads. /maxadselect. /maxi_ad. /mbads? /mbn_ad. /mcad.php /mda-ads/* /mDialogAdModule. /media/ad/* /media/ads/* /media/adv/* /media_ads/* /megaad. /meme_ad. /metaad. /metaadserver/* /metsbanner. /mgid-ad- /mgid-header. /mgid.html /microad. /microads/* /microsofttag/* /middle_adv_ /middleads. /min/ads/* /mini-ads/* /mini_ads. /miniadbar/* /miniads? /minify/ads- /minpagead/* /mint/ads/* /misc/ad- /misc/ads. /misc/ads/* /miva_ads. /MixBerryAdsProduction/* /mjx-oas. /mkadsrv. /mktad. /ml9pagepeel. /mmsAds. /mmt_ad. /mnads1. /mobile-ad. /mobile_ad. /mobile_ad/* /mobileads. /mobilephonesad/* /mod_ad/* /mod_pagepeel_banner/* /modalad. /module-ads/* /module/ads/* /modules/ad/* /modules/ad_ /modules/ads/* /modules/adv/* /modules/doubleclick/* /modules_ads. /momsads. /moneyball/ads/* /mpads/* /mpu-dm.htm /mpuad. /mpuguardian. /mpumessage. /mrskinleftside. /msgads. /msn-1.js /msn-exo- /msnadimg. /msnads/* /msnads1. /msnpop. /msnpopsingle2. /msnpopup. /msnpopup4. /mstextad? /MTA-Ad- /mtvi_ads_ /multiad/* /my-ad-integration. /myads/* /mydirtyhobby.$domain=~mydirtyhobby.com|~mydirtyhobby.de /myfreepaysitebanner. /mylayer-ad/* /mysimpleads/* /n/adv_ /n4403ad. /n_ads/* /namediaad. /nativeads- /nativeads/* /navad/* /navads/* /nbcuadops- /nd_affiliate. /neo/ads/* /neoads. /netads. /netreachtextads/* /netseerads. /netshelter/* /netspiderads2. /netspiderads3. /network_ad. /neudesicad. /new-ads/* /new/ad/* /new/ads/* /new_ads/* /new_oas. /newad. /newad2? /newad? /newads. /newads/* /newadv/* /newadvert/* /newaff/float /newdesign/ad/* /newimages/ads/* /newimplugs. /newrightcolad. /news/ads/* /news_ad. /newsite/ads/* /newsletterads/* /newsletters/ads/* /newsmaxadcontrol. /newtopmsgad. /nextad/* /nflads. /no_ads. /nonrotatingads/* /noticead. /nsfw/sponsors/* /nymag_ads. /nymag_ads_ /o2ad. /o2contentad. /oas-config. /oas.aspx /oas.js /oas/ad/* /oas/banners/* /oas/iframe. /oas/oas- /oas_ad. /oas_ad/* /oas_ad_ /oas_ads. /oas_handler. /oas_home_ /oas_mjx. /oas_mjx1. /oas_mjx2. /oas_mjx3. /oasadconnector. /oasadframe. /oasadfunction. /oasadfunctionlive. /oasbanner_ /oascache/* /oascentral.$~object-subrequest /oascentral/* /oasconfig/* /oascontroller. /oasdefault/* /oasisi- /oasisi. /oasx/* /oiopub-ads/* /oiopub-direct/*$~stylesheet /old/ads- /omb-ad- /ome.ads. /onead. /onesheet-ad- /online/ads/* /online_ads/* /onlineads/* /onplayerad. /ontopadvertising. /openad. /openads- /openads. /openads/* /openads2/* /openads_ /openadserver/* /openx- /openx. /openx/* /openx_ /openxtag. /optonlineadcode. /opxads. /orbitads. /origin-ad- /other/ads/* /outbrain-min. /overlay-ad. /overlay_ad_ /overlayad. /overlayads. /overture.$script,stylesheet /overture/*$script,subdocument /overture_ /ovt_show.asp? /ox/www/* /ox_ultimate/www/* /p2/ads/* /p2ads/* /p8network.js /page-ads. /page-peel /page/ad/* /pagead/ads? /pagead/gen_ /pagead2. /pagead46. /pagead? /pageadimg/* /pageads/* /pagecurl/* /pageear. /pageear/* /pageear_ /pagepeel- /pagepeel. /pagepeel/* /pagepeel_ /pagepeelads. /pages/ads /paidads/* /paidlisting/* /panelad. /park_html_functions.*.js /park_html_functions.js /park_html_functions_general.js /partner_ads/* /partner_ads_ /partnerad. /partnerads/* /partnerads_ /partneradwidget. /partnerbanner. /partnerbanner/* /partners/ad- /partners/ads/* /partners/get-banner. /partnersadbutler/* /parts/ad/* /pauseadextension. /payperpost. /pc/ads. /pcad.js? /peel.js /peel.php? /peel/?webscr= /peel1.js /peel_ads/* /peelad. /peelad/* /peelads/* /peelaway_images/* /peelbackscript/ad_ /peeljs.php /peeltl. /peeltr. /pencilad. /perfads. /performance_ads/* /performancingads/* /permanent/ads/* /pfpadv. /pgad. /pgrightsideads. /photo728ad. /photoad. /photoads/* /photogallaryads. /php/ad/* /php/ads/* /phpads. /phpads/* /phpads2/* /phpadserver/* /phpadsnew/* /phpbanner/banner_ /pic/ads/* /pic_adv/* /pickle-adsystem/* /pics/ads/* /picture/ad/* /pictureads/* /pictures/ads/* /pilot_ad. /pitattoad. /pix/ads/* /pixelads/* /place-ads/* /placead_ /placeholder-ad- /placements/ad_ /play/ad/* /player/ad/* /player/ads. /player/ads/* /player_ads/* /pledgead. /plugin/ad/* /plugins/ad. /plugins/ads/* /plugins/page-cornr- /plugins/wp-moreads/*$~stylesheet /plugins/wp125/*$~stylesheet /plugins/wp_actionpop/* /plugins_ads_ /plus/ad_ /poker-ad. /poll-ad- /pool.ads. /pool/ad/* /pop-under. /pop.js| /pop2.js| /pop_ad. /pop_adfy. /pop_camgirlcity. /pop_under. /pop_under/* /popad- /popad. /popads. /popads/* /popads_ /poplivejasmine. /popounder4. /poprotator. /popshow.$~stylesheet /popu.js /popunder- /popunder. /popunder/* /popunder1. /popunder1_ /popunder2. /popunder4. /popunder5. /popunder7. /popunder? /popunder_ /popunderblogs. /popundercode. /popunderking. /popunders. /popunders/* /popundr. /popundr_ /popup-domination/*$~stylesheet /popup2.js /popup3.js /popup_ad. /popup_code. /popupads. /popupdfp. /popupunder. /post-ad- /post_ads_ /postad. /postprocad. /postprofilehorizontalad. /postprofileverticalad. /posts_ad. /pounder-$~image /ppd_ads. /ppd_ads_ /predictad. /premierebtnad/* /premium_ad. /premiumads/* /premiumadzone. /prerollad. /prerollads. /previews/ad/* /printad. /printad/* /printads/* /PRNAd300x150. /proads/* /proadvertising. /proadvertising_ /processad. /processads. /processing/impressions.asp? /product-ad/* /product-ads/* /production/ads/* /projectwonderful_ /promo/ad_ /promo/ads/* /promo/affiframe. /promo300by250. /promo300x250. /promoads/* /promobuttonad. /promoloaddisplay? /promoredirect?*&campaign=*&zone= /promotion/geoip/* /promotions/ads. /promotions/ads/* /promotions/ads? /promotools. /promotools/* /promotools1. /protection/ad/* /provideadcode. /provider_ads/* /proxxorad. /proxyadcall? /pub/ad/* /pub/ads/* /pub_images/*$third-party /pubad. /pubads. /pubads_ /public/ad/* /public/ad? /public/ads/* /public/adv/* /publicidad.$~object-subrequest,~stylesheet /publicidad/* /publicidad_$~stylesheet /publicidade. /publicidade/* /pubmatic_ /pubs_aff.asp? /puff_ad? /pullads. /punder.js /punder.php /qandaads/* /qd_ads/* /qpon_big_ad /quadadvert. /questions/ads/* /quick_ads/* /quigo_ad /r_ads/* /radioAdEmbed. /radioadembedgenre. /radioAdEmbedGPT. /radopenx? /rail_ad_ /railad. /railads. /railsad. /railsad_ /RainbowTGXServer/* /ram/ads/* /randomad. /randomad120x600nsfw. /randomad160x600nsfw. /randomad2. /randomad300x250nsfw. /randomad728x90nsfw. /randomad_ /randomads. /rawtubelivead. /rcolads1. /rcolads2. /rcom-ads. /rcom-video-ads. /realmedia/ads/* /realmedia_banner. /realmedia_banner_ /realmedia_mjx. /realmedia_mjx_ /reclama/* /reclame/* /recommendations/ad. /recordadsall. /rect_ad. /rectangle_ad. /rectangle_advertorials_ /redirect_awe. /refads/* /refreshads- /refreshsyncbannerad? /RefSplDicAdsTopL. /reklam. /reklam/* /reklama.$~stylesheet /reklama/* /reklama2. /reklama5. /reklame/* /related-ads. /relatedads. /relevance_ad. /remove-ads. /remove_ads. /render-ad/* /repeat_adv. /report_ad. /report_ad_ /requestadvertisement. /requestmyspacead. /resources/ad. /resources/ads/* /resources/ads_ /responsive-ads. /restorationad- /retrad. /retrieve-ad. /revealaads. /revealaads/* /revealads. /revealads/* /revealads2/* /rg-erdr.php$xmlhttprequest /rg-rlog.php$xmlhttprequest /rgads. /rhspushads/* /richoas. /right-ad- /right_ad. /right_ad^ /right_ad_ /right_ads. /rightad. /rightad/* /rightads. /rightbanner/* /rightnavads. /rightnavadsanswer. /rightrailgoogleads. /rightsideaddisplay. /righttopads. /rollad. /rolloverads/* /rolloverbannerad. /root_ad. /rotad/* /rotads/* /rotateads. /rotatedads1. /rotatedads13. /rotatedads2. /rotating_banner.php /rotatingad. /rotatingpeels. /rotatingtextad. /rotation/banner /rotationad. /rotatorad300x250. /rotatoradbottom. /roturl.js /rpc/ad/* /rpgetad. /rsads.js /rsads/* /rsc_ad_ /rss/ads/* /rss2/?*&hp=*&np=$script,third-party /rss2/?*&np=*&hp=$script,third-party /rss2/?hp=*&np=$script,third-party /rss2/?np=*&hp=$script,third-party /rswebsiteads/* /rule34/ads/* /rule34v2/ads/* /safead/* /sailthru.js /salesad/* /samplead1. /samsung_ad. /satnetads. /satnetgoogleads. /savvyads. /sb-relevance.js /scanscout. /scanscoutoverlayadrenderer. /scanscoutplugin. /scaradcontrol. /script/ad. /script/ads. /script/ads_ /script/oas/* /scripts/ad- /scripts/ad. /scripts/ad/* /scripts/ad_ /scripts/ads. /scripts/ads/* /scripts/adv. /scripts/afc/* /scripts/feedmeCaf.php?q=*&d=*&ron=$script /scripts/zanox- /scrollads/* /search-ads? /search.php?uid=*.*&src= /search/ad/* /search/ads? /search/ads_ /search_ads. /searchad. /searchad_ /searchads/* /secondads. /secondads_ /securepubads. /seo-ads. /serv.ads. /serve.ads. /servead. /servead/* /ServeAd? /serveads. /server/ads/* /servewebads/* /service/ads/* /services/ads/* /settings/ad. /sevenads. /sevenl_ad. /share/ads/* /shared/ad_ /shared/ads. /shared/ads/* /shortmediads/* /show-ad. /show-ads. /show.ad? /show.cgi?adp /show_ad. /show_ad_ /show_ads.js /show_ads_ /showad. /showad/* /showAd300- /showAd300. /showad_ /showadcode. /showadjs. /showads. /showads/* /showads_ /showadvert. /showadvertising. /showban.asp? /showbanner. /showcasead/* /showflashad. /showindex-ad- /showJsAd/* /showmarketingmaterial. /showpost-ad- /showsidebar-ad- /side-ad- /side-ad. /side-ads- /side_adverts. /sidead. /sidead/* /sidead1. /sidead2. /sidead3. /sideadiframe. /sideads/* /sideads| /sideadvtmp. /sidebar-ad- /sidebar-ads/* /sidebar_ad. /sidebar_ad_ /sidebar_ads/* /sidebarad/* /sidebaradvertisement. /sidecol_ad. /sidekickads. /sidelinead. /siframead. /silver/ads/* /silverads. /simpleads/* /simpleadvert. /simpleadvert/* /singleadextension. /sisterads. /site-ads/* /site-advert. /site/ads/* /site/ads? /site=*/size=*/viewid= /site=*/viewid=*/size= /site_ads. /site_ads/* /site_under. /siteads. /siteads/* /siteadvert. /siteafs.txt? /sitemanagement/ads/* /sites/ad_ /sitewide/ads/* /size=*/random=*/viewid= /skin/ad/* /skin/ad3/* /skin/adv/* /skin3/ads/* /skinad. /skinads/* /skins/ads- /skins/ads/* /skyad. /skyad_ /skyadjs/* /skyadright. /skybannerview. /skybar_ad. /skyframeopenads. /skyframeopenads_ /skyscraper-ad. /skyscraper_ad_ /skyscraperad. /slafc.js /slideadverts/* /slideinad. /slider-ad- /slider.ad. /slider_ad. /sliderAd/* /sliderad3. /SliderJobAdList. /slideshow/ads. /slideshowintad? /slidetopad. /smalAds. /small_ad. /small_ads/* /smallad- /smalladblockbg- /smalltopl. /smart-ad-server. /smartad- /smartad. /smartAd? /smartads. /smartadserver. /smartlinks.epl? /smb/ads/* /smeadvertisement/* /smedia/ad/* /SmpAds. /socialads. /socialads/* /somaadscaleskyscraperscript. /some-ad. /someads. /sp/delivery/* /spac_adx. /space_ad. /spacedesc= /spark_ad. /spc.php /spcjs.php /spcjs_min. /special-ads/* /special_ad. /special_ads/* /specialads/* /specialfeatureads/* /spiderad/* /splash_ads_ /spo_show.asp? /sponlink. /spons/banners/* /spons_links_ /sponser. /sponseredlinksros. /sponsers.cgi /sponsimages/* /sponslink_ /sponsor%20banners/* /sponsor-ad /sponsor-box? /sponsor-links. /sponsor/click. /sponsor_ads. /sponsor_select. /sponsorad. /sponsoradds/* /sponsorads. /sponsorads/* /sponsorbanners/* /sponsorbg/* /sponsored-backgrounds/* /sponsored-banner- /sponsored-links- /sponsored-links/* /sponsored_ad. /sponsored_ad_ /sponsored_ads/* /sponsored_by. /sponsored_link. /sponsored_links. /sponsored_links1. /sponsored_links_ /sponsored_listings. /sponsored_text. /sponsored_title. /sponsored_top. /sponsoredads/* /sponsoredbanner/* /sponsoredcontent. /sponsoredheadline. /sponsoredlinks. /sponsoredlinks/* /sponsoredlinks? /sponsoredlinksiframe. /sponsoredlisting. /sponsorHeaderDeriv_ /sponsoringbanner/* /sponsorpaynetwork. /sponsors-ads/* /sponsors.js? /sponsors/ads/* /sponsors/amg.php? /sponsors_box. /sponsorsgif. /sponsorshipimage- /sponsorstrips/* /spotlightads/* /spotx_adapter. /spotxchangeplugin. /spotxchangevpaid. /square-ad. /square-ads/* /squaread. /squareads. /src/ads_ /srec_ad_ /srv/ad/* /ss3/ads/* /standard_ads. /static.ad. /static/ad- /static/ad/* /static/ad_ /static/ads/* /static/adv/* /static/js/4728ba74bc.js$~third-party /static_ads/* /staticadslot. /sticker_ad. /sticky_ad. /stickyad. /stickyad2. /storage/ads/* /storage/adv/* /stories/ads/* /story_ad. /story_ads_ /storyadcode. /storyads. /stream-ad. /streamads. /streamatepop. /studioads/* /stuff/ad- /style_ad. /styles/ads. /styles/ads/* /subAd. /subad2_ /subadz. /subnavads/* /subs-ads/* /sugar-ads. /sugar-ads/* /sugarads- /superads_ /supernorthroomad. /survey_monkey. /svnad/* /swf/ad- /swf/ads/* /swfbin/ad- /swfbin/ad3- /swfbin/ad3_ /switchadbanner. /SWMAdPlayer. /synad2. /synad3. /syndication/ad. /sys/ad/* /system/ad/* /system/ads/* /system_ad. /systemad. /systemad_ /t-ads. /t.php?uid=*.*&src= /tabads/* /tableadnorth. /taboola- /tag-adv. /tag_adv/* /tagadv_ /talkads/* /taxonomy-ads. /td-ads- /td_ads/* /tdlads/* /teamplayer-ads. /teaseimg/ads/* /technomedia. /teletoon_ad. /tempads/* /template/ad. /templateadvimages/* /templates/ad. /templates/ads/* /templates/adv_ /testads/* /testingad. /text_ad. /text_ad_ /text_ads. /text_ads_ /textad. /textad/* /textad1. /textad? /textad_ /textadrotate. /textads- /textads. /textads/* /textads_ /textadspromo_ /tfs-ad. /tg.php?uid= /thdgoogleadsense. /thebannerserver.net/* /thirdparty/ad/* /thirdpartyads/* /thirdpartyframedad/* /thumbs/ads/* /thunder/ad. /tickeradsget. /tidaladplugin. /tii_ads. /tikilink? /tileads/* /tinlads. /tinyad. /tit-ads. /title-ad/* /title_ad. /tizers.php? /tl.ads- /tmnadsense- /tmnadsense. /tmo/ads/* /tmobilead. /tncms/ads/* /toggleAds. /toigoogleads. /toolkitads. /tools/ad. /toonad. /top-ad- /top-ad. /top-ad_ /top-ads. /top_ad. /top_ad/* /top_ad_ /top_ads. /top_ads/* /top_ads_ /top_adv_ /topad. /topad/* /topad3. /topad_ /topadbg. /topadfooter. /topadheader. /topads. /topads/* /topads1. /topads2. /topads3. /topads_ /topads| /topadv. /topadvert. /topleftads. /topperad. /toprightads. /tops.ads. /torget_ads. /totalmedia/* /Totem-Cash/* /totemcash/*$image /totemcash1. /tower_ad_ /towerbannerad/* /tr2/ads/* /track.php?click=*&domain=*&uid=$xmlhttprequest /track.php?uid=*.*&d= /track_ad_ /trackads/* /tracked_ad. /trade_punder. /tradead_ /TradeAds/* /tradedoubler. /trafficads. /trafficengineads. /trafficsynergysupportresponse_ /transad. /travidia/* /tremoradrenderer. /triadshow. /tribalad. /tripplead/* /ttz_ad. /turbo_ad. /tvgdartads. /TWBadbanner. /twgetad3. /TwtAd_ /txt_ad. /txt_ad_ /txt_adv. /txtad. /txtads/* /u-ads. /u/ads/* /uberlayadrenderer. /ucstat. /ugoads. /ugoads_inner. /ui/ads/* /ui/adv. /ui/adv_ /uk.ads. /uk/ads/* /ukc-ad. /unibluead. /unity/ad/* /up/ads/* /update_ads/* /update_layer/layer_os_new.php /uplimg/ads/* /upload/ads/* /uploaded/ads/* /uploads/ads/* /uploads/adv/* /uploads/adv_ /upsellingads/* /us-ads. /usenext16. /user_ads/* /userad. /userad/* /userimages/ads/* /usernext. /utep/ad/* /utep_ad.js /v5/ads/* /v9/adv/* /vads/* /valueclick-ad. /valueclick. /valueclickbanner. /valueclickvert. /vast_ads_ /VASTAdPlugin. /vb/ads/* /vboard/ads/* /vbvua.js /vclkads. /vendor-ads- /vericaladtitle. /vert728ad. /vert_ad. /verticaladrotatorv2. /vghd.gif /vghd.swf /vghd2.gif /VHDpoppingModels/* /viagogoads. /vidadv. /video-ad-overlay. /video-ads-player. /video.ads.php? /video/ads/* /video2adrenderer. /video_ad. /video_ad_ /video_ads. /videoad. /videoad_new. /videoadrenderer. /videoads. /videoads/* /VideoAdsServingService/* /videostreaming_ads. /videowall-ad. /view/ads/* /view/banner/* /view_banner. /viewad. /viewad/* /viewad? /viewbannerad. /viewer/rad? /viewid=*/site=*/size= /views/ads/* /virtuagirl. /virtuagirl/* /virtuagirl3. /virtuagirlhd. /virtual_girl_ /virtualgirl/* /virtualgirlhd- /visitoursponsors. /vnads. /vnads/* /vogue_ads/* /vpaidad3. /vpaidadrenderer. /vplayerad. /vtextads. /w/ads/* /wahoha. /wallpaper_ads/* /wallpaperads/* /watchit_ad. /wave-ad- /wbadvert/* /weather-sponsor/* /weather/ads/* /web-ad_ /web-ads. /web-ads/* /web/ads/* /web_ads/* /webad. /WebAd/* /webad? /webadimg/* /webads. /webads/* /webads_ /webadserver. /webadvert. /webadvert/* /webadvert3/* /webadverts/* /webmailad. /webmaster_ads/* /weeklyAdsLabel. /welcome_ad. /welcomead. /welcomeadredirect. /werbebanner/* /widget/ad/* /widget/ads. /widget/ads/* /widgetad. /widgetadsense. /widgets/ads. /wipeads/* /wire/ads/* /wired/ads/* /wix-ad. /wlbetathome/bannerflow/* /wmads. /wordpress-ads-plug-in/* /work.php?n=*&size=*&c= /wp-content/ads/* /wp-content/mbp-banner/* /wp-content/plugins/automatic-social-locker/* /wp-content/plugins/banner-manager/* /wp-content/plugins/bhcb/lock.js /wp-content/plugins/fasterim-optin/* /wp-content/plugins/platinumpopup/* /wp-content/plugins/useful-banner-manager/* /wp-content/plugins/wp-bannerize/* /wp-content/plugins/wp-super-popup-pro/* /wp-content/plugins/wp-super-popup/*$~stylesheet /wp-content/uploads/useful_banner_manager_banners/* /wp-popup-scheduler/* /wp-srv/ad/* /wp_ad_250. /wp_ad_250_ /wpads/iframe. /wpbanners_show.php /wpproads. /wrapper/ads/* /writelayerad. /wwe_ads. /wwe_ads/* /www/ad/* /www/ads/* /www/deliverx/* /www/delivery/* /www/js/ad/* /x5advcorner. /xadvertisement. /xbanner.php? /xclicks. /xfiles/ads/* /xhr/ad/* /xlayer/layer.php?uid=$script /xml/ad/* /xml/ads_ /xmladparser. /xnxx-ads. /xpiads. /xtendmedia.$domain=~xtendmedia.dk /xxxmatch_ /yads- /yads. /yads/* /yads_ /yahoo-ad- /yahoo-ads/* /yahoo/ads. /yahoo_overture. /YahooAd_ /yahooads. /yahooads/* /yahooadsapi. /yahooadsobject. /yahoofeedproxy. /yellowpagesads/* /yhs/ads? /yieldads. /yieldlab. /yieldmanager/* /yin-ad/* /yld/js/* /yld_mgr/* /your-ad- /your-ad. /your_ad. /yourad1. /youradhere. /youradhere468- /youradhere_ /ypad/* /ysc_csc_news /ysmads. /ysmwrapper.js /yume_ad_library_ /z-ads. /z/ads/* /zagcookie_ /zalando-ad- /zanox.js /zanox/banner/* /zanox_ad/* /zedo_ /~cdn/ads/* ://a.ads. ://ad.*/jstag^ ://adcl. ://ads. ://adv.$domain=~forex-tv-online.com ://affiliate.$third-party ://affiliates.$third-party ://ax-d.*/jstag^ ://banner.$third-party ://banners.$third-party ://bwp.*/search ://delivery.*/jstag^ ://feeds.*/~a/ ://findnsave.*.*/api/groupon.json? ://findnsave.*.*/td/portablerop.aspx? ://oas.*@ ://ox-*/jstag^ ://pop-over. ://promo.$third-party ://rss.*/~a/ ://synad. ://wrapper.*/a? :8080/ads/ ;adsense_ ;cue=pre;$object-subrequest ;iframeid=ad_ =ad-leaderboard- =ad-rectangle- =ad320x50- =ad_iframe& =ad_iframe_ =adcenter& =adcode& =adexpert& =adlabs& =admeld& =adMenu& =admodeliframe& =adsCallback& =adscripts& =adsfinal. =adshow& =adslot& =adspremiumplacement& =adtech_ =advert/ =advertiser. =advertiser/ =advertorial& =adView& =akiba_ads_ =banners_ad& =clkads/ =com_ads& =dartad_ =deliverAdFrame& =display_ad& =DisplayAd& =displayAds& =dynamicads& =GetSponsorAds& =half-page-ad& =js_ads& =searchadslider| =showsearchgoogleads& =simpleads/ =tickerReportAdCallback_ =web&ads= =webad2& ?*=x55g%3add4vv4fy. ?action=ads& ?ad_ids= ?ad_size= ?ad_tag= ?ad_type= ?ad_width= ?adarea= ?adclass= ?adcontext= ?adflashid= ?adfox_ ?adloc= ?adlocation= ?adpage= ?adpartner= ?ads= ?adsdata= ?adsite= ?adsize= ?adslot= ?adtag= ?adTagUrl= ?adtarget= ?adtechplacementid= ?adtype= ?adunit_id= ?adunitid= ?adunitname= ?adv/id= ?adversion= ?advertisement= ?advertiser= ?advertiser_id= ?advertiserid=$domain=~outbrain.com ?advertising= ?advideo_ ?advsystem= ?advtile= ?advurl= ?adx= ?adzone= ?banner.id= ?banner_id= ?bannerid= ?bannerXGroupId= ?dfpadname= ?file=ads& ?g1t2h=*&t1m2k3= ?getad=&$~object-subrequest ?goto=ad| ?handler=ads& ?idaffiliation= ?module=ads/ ?OASTagURL= ?phpAds_ ?service=ad& ?sid=ads ?simple_ad_ ?type=ad& ?type=oas_pop& ?view=ad& ?wm=*&prm=rev& ?wpproadszoneid= ?ZoneID=*&PageID=*&SiteID= ?ZoneID=*&Task=*&SiteID= ^fp=*&prvtof= ^mod=wms&do=view_*&zone= ^pid=Ads^ _125ad. _160_ad_ _160x550. _300x250Banner_ _468x60ad. _728x90ad_ _acorn_ad_ _ad&zone= _ad-125x125. _ad.gif| _ad.jsp? _ad.php? _ad.png? _ad/full_ _ad/public/ _ad/section_ _ad01. _ad01_ _ad1.$~stylesheet _ad103. _ad120x120_ _ad1a. _ad1b. _ad2. _ad234x90- _ad3. _ad300. _ad300x250. _ad6. _ad728x90. _ad9. _ad?darttag= _ad?size= _ad_125x125. _ad_2012. _ad_300. _ad_350x250. _ad_actron. _ad_background. _ad_banner. _ad_banner_ _ad_big. _ad_block& _ad_bottom. _ad_box. _ad_bsb. _ad_center. _ad_change. _ad_choices. _ad_choices_ _ad_close. _ad_code. _ad_content. _ad_controller. _ad_count. _ad_count= _ad_courier. _ad_div= _ad_domain_ _ad_end_ _ad_engine/ _ad_expand_ _ad_feed. _ad_footer. _ad_footer_ _ad_frame. _ad_handler. _ad_head. _ad_header. _ad_heading. _ad_homepage. _ad_ids= _ad_iframe. _ad_image_ _ad_images/ _ad_init/ _ad_integration. _ad_interactive. _ad_label. _ad_layer_ _ad_leaderboard. _ad_logo. _ad_middle_ _ad_minileaderboard. _ad_new_ _ad_number= _ad_one. _ad_over_ _ad_page_ _ad_placeholder- _ad_position_ _ad_promo2. _ad_render_ _ad_renderer_ _ad_right. _ad_right_ _ad_run. _ad_service. _ad_serving. _ad_show& _ad_side. _ad_size. _ad_sky. _ad_skyscraper. _ad_slot= _ad_small. _ad_sponsor/ _ad_square. _ad_tall. _ad_template_ _ad_url= _ad_vertical. _ad_view= _ad_widesky. _ad_wrapper. _ad_yellow. _ad_zone_ _adagency/ _adaptvad. _adbanner. _adbanner/ _adbanner_ _adbanners. _adbar. _adbg1a. _adbg2. _adbg2a. _adbit. _adblue. _adbox. _adbox_ _adbreak. _adcall. _adcall_ _adchoice. _adchoices. _adcom. _adcontent/ _adcount= _adengage. _adengage_ _adengine_ _adframe. _adframe/ _adframe_ _adfunction. _adhoc? _adhome. _adhome_ _adhoriz. _adhub_ _adify. _adjug. _adlabel_ _adlesse. _adlib. _adlog. _admanager/ _admarking_ _admin/ads/ _adminka/ _adobjects. _adpage= _adpartner. _adplugin. _adright. _adright2. _adrotator. _adrow- _ads-affiliates_ _ads.cgi _ads.html _ads.js? _ads.php? _ads/horiz/ _ads/horiz_ _ads/iframe. _ads/inhouse/ _ads/ip/ _ads/js/ _ads/square/ _ads1. _ads2. _ads3. _ads? _ads_cached. _ads_contextualtargeting_ _ads_Home. _ads_iframe. _ads_iframe_ _ads_index_ _ads_multi. _ads_new. _ads_only& _ads_reporting. _ads_single_ _ads_targeting. _ads_text. _ads_top. _adsbgd. _adscript. _adsdaq. _adsense. _adsense_ _adserve. _adserve/ _adserved. _adserver. _adserver/ _adsetup. _adsframe. _adshare. _adshow. _adsjs. _adskin. _adskin_ _adsonar. _adspace- _adspace_ _adsrv= _adsrv? _adssource. _adstat. _adsys. _adsystem/ _adtags. _adtech& _adtech- _adtech. _adtech/$~stylesheet _adtech_ _adtext_ _adtitle. _adtoma. _adtop. _adtxt. _adunit. _adv/300. _adv/leaderboard_ _adv/overlay/ _Adv_Banner_ _advert. _advert/ _advert1. _advert_1. _advert_2. _advert_label. _advert_overview. _advert_vert _advertise- _advertise. _advertise180. _advertisehere. _advertisement- _advertisement. _advertisement/ _advertisement_ _advertisementbar. _advertisements/ _advertisementtxt_ _advertising. _advertising/ _advertising_header. _advertising_iframe. _advertisment. _advertorial. _advertorial3. _advertorial_ _advertorials/ _advertphoto. _adverts.js _adverts/ _adverts3. _advertsarea. _AdvertsImgs/ _adview? _adview_ _advservices. _adwrap. _adwriter. _afd_ads. _affiliate/banners/ _affiliate_ad. _afs_ads. _alt/ads/ _argus_ad_ _assets/ads/ _background_ad. _background_ad/ _banner_ad. _banner_ad_ _banner_ads. _Banner_Ads_ _banner_adv_ _bannerad. _BannerAd_ _bannerads_ _bannerview.php?*&aid= _bg_ad_left. _blank_ads. _blogads. _blogads_ _bottom_ads. _bottom_ads_ _box_ad_ _btnad_ _button_ad_ _buttonad. _centre_ad. _cgbanners.php? _ChatAd_ _companionad. _content_ad. _content_ad_ _contest_ad_ _custom_ad. _custom_ad_ _dart_ads. _dart_interstitial. _dashad_ _dfp.php? _displayad_ _displaytopads. _doubleclick. _doubleclick_ad. _down_ad_ _dropdown_ad. _dynamicads/ _elements/ads/ _engine_ads_ _english/adv/ _externalad. _fach_ad. _fbadbookingsystem& _feast_ad. _files/ad. _fixed_ad. _floating_ad_ _floatingad_ _footer_ad_ _framed_ad/ _friendlyduck. _fullscreen_ad. _gads_bottom. _gads_footer. _gads_top. _gallery_ads. _generic_ad. _geobanner. _google_ad. _google_ads. _google_ads/ _google_ads_ _googlead. _grid_ad? _header_ad. _header_ad_ _headerad. _headline_ad. _homad. _home_ad. _home_ad_ _hosting_ad. _house_ad_ _hr_advt/ _iad.html? _iframe_ad_ _images/ad. _images/ad_ _images/ads/ _index_ad. _inlineads. _js/ads.js _jtads/ _juiceadv. _juicyads. _layerad. _leaderboard_ad_ _left_ad. _link_ads- _live/ad/ _load_ad? _logadslot& _longad_ _mailLoginAd. _main_ad. _mainad. _maxi_ad/ _media/ads/ _mmsadbanner/ _Mobile_Ad_ _mpu_widget? _online_ad. _onlinead_ _openx. _openx/ _org_ad. _overlay_ad. _paid_ads/ _paidadvert_ _panel_ads. _partner_ad. _platform_ads. _platform_ads_ _player_ads_ _plus/ads/ _pop_ad. _pop_ad/ _pop_under. _popunder. _popunder_ _popupunder. _post_ads. _preorderad. _prime_ad. _promo_ad/ _psu_ad. _radio_ad_ _railads. _rectangle_ads. _reklama_$domain=~youtube.com _reporting_ads. _request_ad. _response_ad. _right_ad. _right_ads. _right_ads/ _right_ads_ _rightad. _rightad1. _rightad_ _rightmn_ads. _search/ads.js _sectionfront_ad. _show_ads. _show_ads= _sidead. _sidebar_ad. _sidebar_ad_ _sidebarad_ _site_sponsor _skinad. _skybannerview. _skyscraper160x600. _small_ad. _smartads_ _sponsoredlinks_ _square_ad. _static/ads/ _static_ads. _sticky_ad. _StickyAd. _StickyAdFunc. _survey_ad_ _tagadvertising. _temp/ad_ _text_ads. _textad_ _textads. _textads/ _theme/ads/ _tile_ad_ _top_ad. _top_ad_ _topad. _tribalfusion. _UIM-Ads_ _valueclick. _vertical_ad. _video_ads/ _video_ads_ _videoad. _vodaaffi_ _web-advert. _Web_ad. _web_ad_ _webad. _webad_ _WebBannerAd_ _widget_ad. _yahooads/ _your_ad. _zedo. takeover_background. takeover_banner_ ||cacheserve.*/promodisplay/ ||cacheserve.*/promodisplay? ||com/banners/$image,object,subdocument ||online.*/promoredirect?key= ||ox-d.*^auid= ||serve.*/promoload? ! linkbucks.com script /webservices/jsparselinks.aspx?$script ! Common adserver string /mediahosting.engine$script,third-party /Tag.engine$script,third-party ! White papers insert /sl/assetlisting/? ! Peel script /jquery.peelback.js ! Anti-Adblock /ad-blocker.js /adb_detector. /adblock-blocker/* /adblock_detector. /adblock_detector2. /adblock_logger. /adblockdetect. /adblockdetection. /adbuddy. /adsblocker. /anti-adblock/*$~stylesheet /anti_ab. /antiadblock. /blockblock/blockblock.jquery.js /FuckAdBlock-$script /fuckadblock. /no-adblock/* /wp-content/plugins/anti-block/* /wp-content/plugins/anti_ad_blocker/* ! *** easylist:easylist/easylist_general_block_dimensions.txt *** ,160x600; ,468x60- ,468x60; ,728x90, ,970x90; -120-600. -120_600_ -120x240. -120x300. -120x400. -120x60- -120x60. -120x600- -120x600. -120x600_ -120x600c. -125x40- -160-600. -160x400- -160x600- -160x600. -160x600_ -160x600b. -161x601- -300-250. -300x250-$~xmlhttprequest -300x250_ -300x600. -460x68. -468-100. -468-60- -468-60. -468-60_ -468_60. -468by60. -468x060- -468x060_ -468x60- -468x60. -468x60/ -468x60_ -468x60px- -468x70. -468x80- -468x80. -468x80/ -468x80_ -468x90. -480x120. -480x60- -480x60. -480x60/ -480x60_ -486x60. -500x100. -600x70. -600x90- -700-200. -720x120- -720x90- -720x90. -728-90. -728.90. -728x90& -728x90- -728x90. -728x90/ -728x90_ -728x90a_ -728x90px2. -729x91- -780x90- -800x150. -980x60- -988x60. .120x600. .160x600. .160x600_ .300x250. .300x250_ .468x60- .468x60. .468x60/ .468x60_ .468x80- .468x80. .468x80/ .468x80_ .480x60- .480x60. .480x60/ .480x60_ .650x100. .728x90- .728x90. .728x90/ .728x90_ .900x100. /120-600- /120-600. /1200x70_ /120_600. /120_600/* /120_600_ /120x240_ /120x600- /120x600. /120x600/* /120x600_ /125x240/* /125x300_ /125x400/* /125x600- /125x600_ /130x600- /130x600. /150-500. /150_500. /150x200- /150x300_ /150x600_ /160-600- /160-600. /160.html$subdocument /160_600. /160_600_ /160x400- /160x400_ /160x600- /160x600. /160x600/* /160x600_ /160x600partner. /170x700. /180x150- /190_900. /190x600. /230x90_ /234x60/* /270x90- /300-250- /300-250. /300.html$subdocument /300_250_ /300x150_ /300x250- /300x250. /300x250/* /300x250_ /300x250b. /300x250px- /300x250px_ /300x350. /300x90_ /320x250. /335x205_ /336x280- /336x280. /336x280_ /340x85_ /4-6-8x60. /400x250/* /400x297. /428x60. /460x60. /460x80_ /468-20. /468-60- /468-60. /468-60_ /468_60. /468_60_ /468_80. /468_80/* /468x060. /468x060_ /468x280. /468x280_ /468x60- /468x60. /468x60/* /468x60_ /468x60a. /468x60a_ /468x60b. /468x60v1_ /468x70- /468x72. /468x72_ /468x80- /468x80. /468x80/* /468x80_ /468x80b. /468x80g. /470x030_ /475x150- /480x030. /480x030_ /480x60- /480x60. /480x60/* /480x60_ /480x70_ /486x60_ /496_98_ /500x90. /530x60_ /540x80_ /600-60. /600-90. /600_120_ /600_90_ /600x160_ /600x75_ /600x90. /60x468. /640x100/* /640x80- /660x120_ /660x60. /700_100_ /700_200. /700x100. /700x120. /700x250. /700x90. /728-90- /728-90. /728-90/* /728-90_ /728.html$subdocument /728_200. /728_200_ /728_90. /728_90/* /728_90_ /728_90n. /728by90_ /728x15. /728x180- /728x79_ /728x90- /728x90. /728x90/* /728x901. /728x90? /728x90_ /728x90b. /728x90b/* /728x90d. /728x90g. /728x90h. /728x90l. /728x90top. /750-100. /750x100. /760x120. /760x120_ /760x90_ /768x90- /768x90. /780x90. /800x90. /80x468_ /900x130_ /900x350_ /950_250. /960_60_ /980x90. /_iframe728x90. /ban468. /bottom728.html /bottom728x90. /head486x60. /img/468_60 /img/728_90 /L300xH250/* /lightake728x90. /new160x600/* /new300x250/* /top468.html /top728.html /top728x90. 120-600.gif| 120x500.gif| 120x600.gif? 120x600.gif| 120x600.html| 120x600.htm| 120x600.png| 120x600.swf? 120x600.swf| 125x600.gif| 125x600.swf? 125x600.swf| 133x394.gif| 160x300.gif| 160x600.gif| 160x600.html| 160x600.htm| 160x600.jpg| 160x600.php? 160x600.php| 160x600.png| 160x600.swf? 160x600.swf| 160x6001.jpg| 450x55.jpg| 460x70.jpg| 468-60.gif| 468-60.swf? 468-60.swf| 468_60.gif| 468x60.gif| 468x60.html| 468x60.htm| 468x60.jpg| 468x60.php? 468x60.php| 468x60.swf? 468x60.swf| 468x60_1.gif| 468x60_2.jpg| 468x80.gif| 470x60.gif| 470x60.jpg| 470x60.swf? 470x60.swf| 480x60.png| 480x80.jpg| 700_200.gif| 700_200.jpg| 700x200.gif| 728x290.gif| 728x90.gif| 728x90.html| 728x90.htm| 728x90.jpg| 728x90.php? 728x90.php| 728x90.png| 728x90.swf? 728x90.swf| 728x90_2.jpg| 750x80.swf| 750x90.gif| 760x90.jpg| 80x468.jpg| =120x600, =120x600; =160x160; =160x600& =160x600, =160x600; =234x60; =234x60_ =300x250& =300x250, =300x250/ =300x250; =300x250_ =300x300; =336x280, =336x280; =440x410; =468x60& =468x60, =468x60/ =468x60; =468x60_ =468x80_ =480x60; =728x90& =728x90, =728x90/ =728x90; =728x90_ =760x120& =888x10; =900x60; _100x480_ _115x220. _120_60. _120_600. _120_600_ _120_x_600. _120h600. _120x240. _120x240_ _120x500. _120x60. _120x600- _120x600. _120x600_ _120x600a. _120x600px. _120x60_ _120x800a. _125x600_ _140x600. _140x600_ _150x700_ _160-600. _160_600. _160_600_ _160by600_ _160x1600. _160x290. _160x300. _160x300_ _160x350. _160x400. _160x500. _160x600& _160x600- _160x600. _160x600/ _160x600_ _160x600b. _180x300_ _180x450_ _200x600_ _300-250- _300.htm _300_250. _300_250_ _300_60_ _300x160_ _300x250- _300x250. _300x250_ _300x250a_ _300x250b. _300x250px. _300x250v2. _300x600. _300x600_ _320x250_ _323x120_ _336x120. _336x280_ _336x280a. _336x280s. _336x850. _350_100. _350_100_ _350x100. _370x270. _400-80. _400x60. _400x68. _420x80. _420x80_ _438x50. _438x60. _438x60_ _460_60. _460x60. _465x110_ _468-60. _468.gif _468.htm _468_60- _468_60. _468_60_ _468_80. _468_80_ _468x060- _468x060. _468x060_ _468x100. _468x100_ _468x120. _468x60- _468x60. _468x60/ _468x60_ _468x60b. _468x60px_ _468x6o_ _468x80- _468x80. _468x80/ _468x80_ _468x90. _468x90_ _480_60. _480_80_ _480x60- _480x60. _480x60/ _480x60_ _486x60. _486x60_ _490-90_ _500x440. _540_70. _540_70_ _550x150. _555x70. _580x100. _585x75- _585x75_ _590x105. _600-90. _600x120_ _600x160. _600x180. _600x80. _600x90. _620x203_ _638x200_ _650x350. _650x80_ _672x120_ _680x93_ _682x90_ _700_100_ _700_150_ _700_200_ _700x200. _720_90. _720x90. _720x90_ _728-90. _728-90_ _728.htm _728_90. _728_90_ _728_x_90_ _728by90_ _728x-90. _728x150. _728x60. _728x90& _728x90- _728x90. _728x90/ _728x901. _728x90_ _728x90a. _728x90a_ _728x90b_ _728x90pg_ _728x90px- _728x90px. _728x90px_ _728x90v1. _730_440. _730x60_ _730x90_ _745_60. _745_90. _750x100. _760x100. _760x90_ _764x70. _764x70_ _768x90_ _796x110_ _798x99_ _800x100. _800x80_ _80x468. _900x350. _936x60. _960_90. _970x30_ _980x100. _a468x60. ! *** easylist:easylist/easylist_general_block_popup.txt *** &link_type=offer$popup,third-party &program=revshare&$popup -ads-campaign/$popup .co/ads/$popup .com/?adv=$popup .com/ads?$popup .engine?PlacementId=$popup /?placement=*&redirect$popup /ad.php?tag=$popup /ad.php|$popup /ad/window.php?$popup /ad132m/*$popup /ad_pop.php?$popup /adclick.$popup /AdHandler.aspx?$popup /ads.htm$popup /adServe/sa?cid=$popup /adserver.$popup /adstream_sx.ads/*$popup /advlink.$popup /afu.php?$popup /bani/index.php?id=$popup /lr.php?zoneid=$popup /popout.$popup /popunder.$popup /popunder_$popup /popupads.$popup /promoredirect?*&campaign=*&zone=$popup /punder.php$popup /realmedia/ads/*$popup /Redirect.eng?$popup /Redirect.engine$popup /servlet/ajrotator/*$popup /spopunder^$popup ://ads.$popup ://adv.$popup =popunder&$popup =popunders&$popup ?AdUrl=$popup ?bannerid=*&punder=$popup ?zoneid=*_bannerid=$popup _popunder+$popup !------------------------General element hiding rules-------------------------! ! *** easylist:easylist/easylist_general_hide.txt *** ###A9AdsMiddleBoxTop ###A9AdsOutOfStockWidgetTop ###A9AdsServicesWidgetTop ###AD-300x250 ###AD-HOME-LEFT ###AD1line ###AD2line ###AD300_VAN ###AD300x250 ###AD300x600 ###ADEXPERT_PUSHDOWN ###ADEXPERT_RECTANGLE ###ADInterest ###ADNETwallBanner1 ###ADNETwallBanner2 ###ADSLOT_1 ###ADSLOT_2 ###ADSLOT_3 ###ADSLOT_4 ###ADSLOT_SKYSCRAPER ###ADS_2 ###ADSlideshow ###ADSpro ###ADV120x90 ###ADVERTISE_HERE_ROW ###ADVleaderboard ###AD_160 ###AD_300 ###AD_468x60 ###AD_C ###AD_CONTROL_13 ###AD_CONTROL_22 ###AD_CONTROL_28 ###AD_CONTROL_29 ###AD_CONTROL_8 ###AD_G ###AD_ROW ###AD_Top ###AD_Zone ###AD_banner ###AD_banner_bottom ###AD_gallery ###AD_google ###AD_half ###AD_newsblock ###AD_rectangle ###AD_rr_a ###ADgoogle_newsblock ###ADoverThePlayer ###ADsmallWrapper ###AFF_popup ###APC_ads_details ###AUI_A9AdsMiddleBoxTop ###Ad-0-0-Slider ###Ad-0-1-Slider ###Ad-1-0-Slider ###Ad-1-1-Slider ###Ad-1-2-Slider ###Ad-3-Slider ###Ad-4-Slider ###Ad-5-2-Slider ###Ad-8-0-Slider ###Ad-9-0-Slider ###Ad-Container ###Ad-Top ###Ad160x600 ###Ad160x600_0_adchoice ###Ad300x145 ###Ad300x250 ###Ad300x250_0 ###Ad300x600_0_adchoice ###Ad3Left ###Ad3Right ###Ad3TextAd ###Ad728x90 ###Ad990 ###AdAboveGame ###AdArea ###AdAreaH ###AdAuth1 ###AdAuth2 ###AdAuth3 ###AdAuth4 ###AdBanner ###AdBannerSmallContainer ###AdBanner_F1 ###AdBanner_S ###AdBar ###AdBar1 ###AdBigBox ###AdBlock ###AdBlockBottomSponsor ###AdBottomLeader ###AdBottomRight ###AdBox160 ###AdBox2 ###AdBox300 ###AdBox728 ###AdBoxMoreGames ###AdButtons ###AdColumn ###AdContainer ###AdContainerTop ###AdContentModule_F ###AdContent_0_0_pnlDiv ###AdControl_TowerAd ###AdDetails_GoogleLinksBottom ###AdDetails_InsureWith ###AdDetails_SeeMoreLink ###AdDisclaimer ###AdDisplay_LongLink ###AdDisplay_TallLink ###AdDiv ###AdExtraBlock ###AdFeedbackLinkID_lnkItem ###AdFoxDiv ###AdFrame1 ###AdFrame2 ###AdFrame4 ###AdHeader ###AdHouseRectangle ###AdImage ###AdIndexTower ###AdLayer1 ###AdLayer2 ###AdLeaderboard2RunofSite ###AdLeaderboardBottom ###AdLeaderboardTop ###AdLocationMarketPage ###AdMPUHome ###AdMediumRectangle1300x250 ###AdMediumRectangle2300x250 ###AdMiddle ###AdMobileLink ###AdPanel ###AdPanelBigBox ###AdPanelLogo ###AdPopUp ###AdRectangle ###AdRectangleBanner ###AdSense-Skyscraper ###AdSense1 ###AdSense2 ###AdSense3 ###AdSenseBottomAds ###AdSenseDiv ###AdSenseMiddleAds ###AdSenseResults1_adSenseSponsorDiv ###AdSenseTopAds ###AdServer ###AdShopSearch ###AdShowcase ###AdShowcase_F ###AdShowcase_F1 ###AdSky23 ###AdSkyscraper ###AdSlot_AF-Right-Multi ###AdSpaceLeaderboard ###AdSpacing ###AdSponsor_SF ###AdSpotMovie ###AdSquare02 ###AdSubsectionShowcase_F1 ###AdTaily_Widget_Container ###AdTargetControl1_iframe ###AdTop ###AdTopBlock ###AdTopLeader ###AdWidgetContainer ###AdZone1 ###AdZone2 ###Ad_976x105 ###Ad_BelowContent ###Ad_Block ###Ad_Center1 ###Ad_Premier ###Ad_Right1 ###Ad_RightBottom ###Ad_RightTop ###Ad_TopLeaderboard ###Adbanner ###Adc1_AdContainer ###Adc2_AdContainer ###Adc3_AdContainer ###AdcBB_AdContainer ###Adcode ###Adrectangle ###Ads470by50 ###AdsBannerTop ###AdsBottomContainer ###AdsBottomIframe ###AdsCarouselBoxArea ###AdsContainerTop ###AdsContent ###AdsContent_SearchShortRecB_UPSSR ###AdsDiv ###AdsFrame ###AdsHome2 ###AdsLeader ###AdsLeft_1 ###AdsPlayRight_1 ###AdsRight ###AdsShowCase ###AdsTopContainer ###AdsVideo250 ###AdsWrap ###Ads_BA_BUT_box ###Ads_BA_CAD ###Ads_BA_CAD2 ###Ads_BA_CAD2_Text ###Ads_BA_CAD_box ###Ads_BA_FLB ###Ads_BA_SKY ###Ads_CAD ###Ads_OV_BS ###Ads_Special ###Ads_google_01 ###Ads_google_02 ###Ads_google_03 ###Ads_google_04 ###Ads_google_05 ###Adsense300x250 ###Adtag300x250Bottom ###Adtag300x250Top ###Adv10 ###Adv11 ###Adv8 ###Adv9 ###AdvArea ###AdvBody ###AdvContainer ###AdvContainerBottom ###AdvContainerMiddleRight ###AdvContainerTopCenter ###AdvContainerTopRight ###AdvFooter ###AdvFrame1 ###AdvHead ###AdvHeader ###Adv_Footer ###Adv_Main_content ###Advert1 ###AdvertMPU23b ###AdvertPanel ###AdvertText ###AdvertiseFrame ###Advertisement1 ###AdvertisementRightColumnRectangle ###Advertisements ###AdvertisingLeaderboard ###AdvertismentHomeTopRight ###Advertorial ###Advertorials ###AdvertsBottom ###AdvertsBottomR ###Adverts_AdDetailsBottom_300x600 ###Adverts_AdDetailsMiddle_300x250 ###ArticleBottomAd ###BANNER_160x600 ###BANNER_300x250 ###BANNER_728x90 ###BBCPH_MCPH_MCPH_P_ArticleAd1 ###BBCPH_MCPH_MCPH_P_OasAdControl1Panel ###BBCPH_MCPH_MCPH_P_OasAdControl2Panel ###BBCPH_MCPH_MCPH_SponsoredLinks1 ###BBoxAd ###BDV_fullAd ###BackgroundAdContainer ###Banner300x250Module ###Banner728x90 ###BannerAd ###BannerAds ###BannerAdvert ###BannerAdvertisement ###BannerXGroup ###BelowFoldAds ###BigBoxAd ###BigboxAdUnit ###BillBoardAdd ###BodyAd ###BotAd ###Bottom468x60AD ###BottomAd0 ###BottomAdContainer ###BottomAdSpacer ###BottomAds ###BottomPageAds ###BrokerBox-AdContainer ###ButtonAd ###CONTENTAD ###CSpromo120x90 ###ClickPop_LayerPop_Container ###CommonHeaderAd ###CompanyDetailsNarrowGoogleAdsPresentationControl ###CompanyDetailsWideGoogleAdsPresentationControl ###ContentAd ###ContentAd1 ###ContentAd2 ###ContentAdPlaceHolder1 ###ContentAdPlaceHolder2 ###ContentAdView ###ContentAdXXL ###ContentAdtagRectangle ###ContentPlaceHolder1_adds ###ContentPlaceHolder1_advertControl1_advertLink ###ContentPlaceHolder1_advertControl3_advertLink ###ContentPolepositionAds_Result ###ConversationDivAd ###CornerAd ###CountdownAdvert ###DARTad300x250 ###DEFAULT_ADV4_SWF ###DFM-adPos-bottomline ###DFPAD_MR ###DFP_in_article_mpu ###DFP_top_leaderboard ###DartAd300x250 ###DartAd990x90 ###DealsPageSideAd ###DivAd ###DivAd1 ###DivAd2 ###DivAd3 ###DivAdA ###DivAdB ###DivAdC ###DivAdEggHeadCafeTopBanner ###DivAdForumSplitBottom ###DivMsnCamara ###DivTopAd ###DividerAd ###FFN_imBox_Container ###FIN_300_250_position2_ad ###FIN_300_x_250_600_position2_ad ###FIN_300x250_pos1_ad ###FIN_300x80_facebook_ad ###FIN_468x60_sponsor_ad ###FIN_640x60_promo_ad ###FIN_728_90_leaderboard_ad ###FIN_ad_300x100_pos_1 ###FIN_videoplayer_300x250ad ###FooterAd ###FooterAdBlock ###FooterAdContainer ###ForumSponsorBanner ###Freeforums-AdS-footer-728x90 ###Freeforums-AdS-header-728x90 ###FrontPageRectangleAd ###GOOGLEADS_BOT ###GOOGLEADS_CENTER ###GOOGLE_ADS_13 ###GOOGLE_ADS_151 ###GOOGLE_ADS_16 ###GOOGLE_ADS_2 ###GOOGLE_ADS_49 ###GOOGLE_ADS_56 ###GOOGLE_ADS_94 ###GameMediumRectangleAD ###GamePageAdDiv ###GoogleADsense ###GoogleADthree ###GoogleAd ###GoogleAd1 ###GoogleAd2 ###GoogleAd3 ###GoogleAdExploreMF ###GoogleAdRight ###GoogleAdTop ###GoogleAds250X200 ###GoogleAdsPlaceHolder ###GoogleAdsPresentationControl ###GoogleAdsense ###GoogleAdsenseMerlinWrapper ###GoogleLeaderBoardAdUnit ###GoogleLeaderBoardAdUnitSeperator ###GoogleRelatedAds ###GoogleSponsored ###Google_Adsense_Main ###HALExchangeAds ###HALHouseAd ###HB_News-ad ###HEADERAD ###HOME_TOP_RIGHT_BOXAD ###HP_adUnits ###H_Ad_728x90 ###H_Ad_Wrap ###HeaderAD ###HeaderAdBlock ###HeaderAdSidebar ###HeaderAdsBlock ###HeaderAdsBlockFront ###HeaderBannerAdSpacer ###HeaderTextAd ###HeroAd ###HomeAd1 ###HomeBannerAd ###Home_AdSpan ###HomepageAdSpace ###HorizontalAd ###HouseAd ###HouseAdInsert ###ID_Ad_Sky ###IM_AD ###IN_HOUSE_AD_SWITCHER_0 ###IframeAdBannerSmallContainer ###ImageAdSideColumn ###ImageRotaAreaAD ###IslandAd_DeferredAdSpacediv ###JobsearchResultsAds ###Journal_Ad_125 ###Journal_Ad_300 ###JuxtapozAds ###KH-contentAd ###LB_Row_Ad ###LargeRectangleAd ###LeaderTop-ad ###LeaderboardAdvertising ###LeaderboardNav_ad_placeholder ###LeftAd ###LeftAd1 ###LeftAdF1 ###LeftAdF2 ###LeftSideBarAD ###LftAd ###LittleAdvert ###LoungeAdsDiv ###LovelabAdoftheDay ###LowerContentAd ###MAINAD-box ###MPUAdSpace ###MPUadvertising ###MPUadvertisingDetail ###M_AD ###MainAd ###MainAd1 ###MainContent_ucTopRightAdvert ###MainSponsoredLinks ###MastheadAd ###MediumRectangleAD ###Meebo\:AdElement\.Root ###MidPageAds ###Module-From_Advertisers ###MyAdHeader ###MyAdSky ###NavAD ###Nightly_adContainer ###NormalAdModule ###OAS2 ###OAS_AD_TOPRIGHT ###OAS_Top ###OAS_posBottom ###OAS_posRight ###OAS_posTopRight ###OpenXAds ###OverrideAdArea ###PPX_imBox_Container ###PREFOOTER_LEFT_BOXAD ###PREFOOTER_RIGHT_BOXAD ###PageLeaderAd ###PaneAdvertisingContainer ###PhotoAd1 ###PostSponsorshipContainer ###PreRollAd ###RHS2Adslot ###RadAdSkyscraper ###RadAd_Skyscraper ###RelevantAds ###RgtAd1 ###RhsIsland_DeferredAdSpacediv ###RightAd ###RightAdBlock ###RightAdSpace ###RightAdvertisement ###RightBottom300x250AD ###RightColumn125x125AD ###RightColumnSkyScraperAD ###RightNavTopAdSpot ###RightRailSponsor ###RightSponsoredAd ###RollOutAd970x66 ###RollOutAd970x66iframe ###SE20-ad-container ###SE_ADLINK_LAY_gd ###SIDEMENUAD ###SRPadsContainer ###ScoreboardAd ###SearchAd_PlaceHolder ###SearchAdsBottom ###SearchAdsTop ###Section-Ads ###SectionAd300-250 ###SectionSponsorAd ###SideAdMpu ###SideBarAdWidget ###SideMpuAdBar ###SidebarAdContainer ###SkyAd ###SpecialAds ###Spons-Link ###SponsorBarWrap ###SponsoredAd ###SponsoredAds ###SponsoredLinks ###SponsoredResultsTop ###SponsorsAds ###TDads ###TL_footer_advertisement ###TOPADS ###TOP_ADROW ###TOP_RIGHT_BOXAD ###TPVideoPlayerAd300x250 ###Tadspacecbar ###Tadspacefoot ###Tadspacehead ###Tadspacemrec ###TextLinkAds ###ThreadAd ###TipTopAdSpace ###TitleAD ###Top-Ad-Container ###Top468x60AD ###TopAd ###TopAd0 ###TopAdBox ###TopAdContainer ###TopAdDiv ###TopAdPlacement ###TopAdPos ###TopAdTable ###TopAdvert ###TopBannerAd ###TopGoogleCustomAd ###TopSideAd ###VM-MPU-adspace ###VM-footer-adspace ###VM-footer-adwrap ###VM-header-adspace ###VM-header-adwrap ###VertAdBox ###VertAdBox0 ###WNAd1 ###WNAd103 ###WNAd17 ###WNAd20 ###WNAd41 ###WNAd43 ###WNAd46 ###WNAd47 ###WNAd49 ###WNAd52 ###WNAd63 ###WarningCodecBanner ###WelcomeAd ###WindowAdHolder ###XEadLeaderboard ###XEadSkyscraper ###YahooAdParentContainer ###YahooAdsContainer ###YahooAdsContainerPowerSearch ###YahooContentAdsContainerForBrowse ###YahooSponsoredResults ###_ads ###a4g-floating-ad ###a_ad10Sp ###a_ad11Sp ###abHeaderAdStreamer ###ab_adblock ###about_adsbottom ###above-comments-ad ###above-fold-ad ###above-footer-ads ###aboveAd ###aboveGbAd ###aboveNodeAds ###aboveplayerad ###abovepostads ###acAdContainer ###acm-ad-tag-300x250-atf ###acm-ad-tag-300x250-btf ###acm-ad-tag-728x90-atf ###acm-ad-tag-728x90-btf ###ad-0 ###ad-1 ###ad-1000x90-1 ###ad-109 ###ad-118 ###ad-120-left ###ad-120x600-1 ###ad-120x600-other ###ad-120x600-sidebar ###ad-120x60Div ###ad-125x125 ###ad-13 ###ad-133 ###ad-143 ###ad-160 ###ad-160-long ###ad-160x600 ###ad-160x600-sidebar ###ad-160x600-wrapper ###ad-162 ###ad-17 ###ad-170 ###ad-180x150-1 ###ad-19 ###ad-197 ###ad-2 ###ad-2-160x600 ###ad-21 ###ad-213 ###ad-220x90-1 ###ad-230x100-1 ###ad-240x400-1 ###ad-240x400-2 ###ad-250 ###ad-250x300 ###ad-28 ###ad-29 ###ad-3 ###ad-3-300x250 ###ad-300 ###ad-300-250 ###ad-300-additional ###ad-300-detail ###ad-300-sidebar ###ad-300a ###ad-300b ###ad-300x-container ###ad-300x250 ###ad-300x250-01 ###ad-300x250-02 ###ad-300x250-1 ###ad-300x250-2 ###ad-300x250-right ###ad-300x250-right0 ###ad-300x250-sidebar ###ad-300x250-wrapper ###ad-300x250Div ###ad-300x40-1 ###ad-300x40-2 ###ad-300x40-5 ###ad-300x60-1 ###ad-32 ###ad-320 ###ad-336 ###ad-350 ###ad-37 ###ad-376x280 ###ad-4 ###ad-4-300x90 ###ad-5-images ###ad-55 ###ad-63 ###ad-635x40-1 ###ad-655 ###ad-7 ###ad-728 ###ad-728-90 ###ad-728x90 ###ad-728x90-1 ###ad-728x90-leaderboard-top ###ad-728x90-top ###ad-728x90-top0 ###ad-74 ###ad-88 ###ad-88-wrap ###ad-970 ###ad-98 ###ad-a ###ad-a1 ###ad-abs-b-0 ###ad-abs-b-1 ###ad-abs-b-10 ###ad-abs-b-2 ###ad-abs-b-3 ###ad-abs-b-4 ###ad-abs-b-5 ###ad-abs-b-6 ###ad-abs-b-7 ###ad-absolute-160 ###ad-ads ###ad-adsensemedium ###ad-advertorial ###ad-affiliate ###ad-area ###ad-article ###ad-article-in ###ad-background ###ad-ban ###ad-banner ###ad-banner-1 ###ad-banner-970 ###ad-banner-980 ###ad-banner-atf ###ad-banner-body-top ###ad-banner-bottom ###ad-banner-image ###ad-banner-top ###ad-banner-wrap ###ad-bar ###ad-base ###ad-beauty ###ad-below-content ###ad-bg ###ad-big ###ad-bigbox ###ad-bigsize ###ad-billboard ###ad-billboard-atf ###ad-billboard-bottom ###ad-blade ###ad-block ###ad-block-125 ###ad-block-bottom ###ad-block-container ###ad-border ###ad-bottom ###ad-bottom-300x250 ###ad-bottom-banner ###ad-bottom-right-container ###ad-bottom-wrapper ###ad-bottomright ###ad-box ###ad-box-1 ###ad-box-2 ###ad-box-bottom ###ad-box-first ###ad-box-second ###ad-box1 ###ad-box2 ###ad-boxATF ###ad-boxes ###ad-br-container ###ad-bs ###ad-btm ###ad-buttons ###ad-campaign ###ad-carousel ###ad-case ###ad-center ###ad-circfooter ###ad-code ###ad-col ###ad-colB-1 ###ad-column ###ad-container ###ad-container-1 ###ad-container-2 ###ad-container-adaptive-1 ###ad-container-adaptive-3 ###ad-container-fullpage ###ad-container-inner ###ad-container-leaderboard ###ad-container-outer ###ad-contentad ###ad-cube-Bottom ###ad-cube-Middle ###ad-cube-sec ###ad-cube-top ###ad-desktop-wrap ###ad-discover ###ad-display-ad ###ad-div-leaderboard ###ad-double-spotlight-container ###ad-e-container ###ad-ear ###ad-extra-flat ###ad-f-container ###ad-featured-right ###ad-first-post ###ad-five ###ad-five-75x50s ###ad-flex-first ###ad-flex-top ###ad-footer ###ad-footer-728x90 ###ad-footprint-160x600 ###ad-for-map ###ad-frame ###ad-framework-top ###ad-front-btf ###ad-front-footer ###ad-front-page-160x600-placeholder ###ad-front-sponsoredlinks ###ad-fullbanner-btf ###ad-fullbanner-outer ###ad-fullbanner2 ###ad-fullwidth ###ad-giftext ###ad-globalleaderboard ###ad-google-chrome-sidebar ###ad-googleAdSense ###ad-gutter-left ###ad-gutter-right ###ad-halfpage ###ad-header ###ad-header-728x90 ###ad-header-left ###ad-header-right ###ad-holder ###ad-homepage-content-well ###ad-homepage-top-wrapper ###ad-horizontal-header ###ad-horizontal-top ###ad-img ###ad-in-post ###ad-index ###ad-inner ###ad-inside1 ###ad-inside2 ###ad-introtext ###ad-label ###ad-label2 ###ad-large-header ###ad-lb ###ad-lb-secondary ###ad-ldr-spot ###ad-leader ###ad-leader-atf ###ad-leader-container ###ad-leaderboard ###ad-leaderboard-1 ###ad-leaderboard-1-container ###ad-leaderboard-2 ###ad-leaderboard-2-container ###ad-leaderboard-bottom ###ad-leaderboard-container ###ad-leaderboard-footer ###ad-leaderboard-spot ###ad-leaderboard-top ###ad-leadertop ###ad-left ###ad-left-sidebar-ad-1 ###ad-left-sidebar-ad-2 ###ad-left-sidebar-ad-3 ###ad-links-content ###ad-list-row ###ad-lrec ###ad-main ###ad-main-bottom ###ad-main-top ###ad-makeup ###ad-manager ###ad-manager-ad-bottom-0 ###ad-manager-ad-top-0 ###ad-medium ###ad-medium-lower ###ad-medium-rectangle ###ad-medrec ###ad-medrec_premium ###ad-megaban2 ###ad-mid-rect ###ad-middle ###ad-middlethree ###ad-middletwo ###ad-midpage ###ad-minibar ###ad-module ###ad-mpu ###ad-mpu-warning ###ad-mpu1-spot ###ad-mpu2 ###ad-mpu2-spot ###ad-mrec ###ad-mrec2 ###ad-new ###ad-north ###ad-north-base ###ad-northeast ###ad-one ###ad-other ###ad-overlay ###ad-panel ###ad-pencil ###ad-placard ###ad-placeholder ###ad-placement ###ad-plate ###ad-popup1 ###ad-position-a ###ad-post ###ad-push ###ad-pushdown ###ad-r ###ad-rbkua ###ad-rec-atf ###ad-rec-btf-top ###ad-recommend ###ad-rect ###ad-rectangle ###ad-rectangle-flag ###ad-rectangle1 ###ad-rectangle1-outer ###ad-rectangle2 ###ad-rectangle3 ###ad-region-1 ###ad-results ###ad-rian ###ad-right ###ad-right-3 ###ad-right-sidebar-ad-1 ###ad-right-sidebar-ad-2 ###ad-right-skyscraper-container ###ad-right-top ###ad-right2 ###ad-right3 ###ad-righttop ###ad-rotator ###ad-row ###ad-row-1 ###ad-s1 ###ad-safe ###ad-section ###ad-separator ###ad-shop ###ad-side ###ad-side-text ###ad-sidebar ###ad-sidebar-1 ###ad-sidebar-2 ###ad-sidebar-3 ###ad-sidebar-300x80 ###ad-sidebar-btf ###ad-sidebar-container ###ad-sidebar1 ###ad-sidebar2 ###ad-single-spotlight-container ###ad-skin ###ad-sky ###ad-sky-atf ###ad-sky-btf ###ad-skyscraper ###ad-skyscraper-feedback ###ad-sla-sidebar300x250 ###ad-slot-1 ###ad-slot-2 ###ad-slot-4 ###ad-slot-right ###ad-slot1 ###ad-slug-wrapper ###ad-small-banner ###ad-software-description-300x250-placeholder ###ad-software-sidebar-300x250-placeholder ###ad-space ###ad-space-1 ###ad-space-2 ###ad-space-big ###ad-special ###ad-splash ###ad-sponsored-traffic ###ad-sponsors ###ad-spot ###ad-spot-bottom ###ad-spot-one ###ad-squares ###ad-story-bottom-in ###ad-story-bottom-out ###ad-story-right ###ad-story-top ###ad-stripe ###ad-tab ###ad-tail-placeholder ###ad-tape ###ad-target ###ad-target-Leaderbord ###ad-teaser ###ad-techwords ###ad-text ###ad-textad-single ###ad-three ###ad-tlr-spot ###ad-top ###ad-top-300x250 ###ad-top-banner ###ad-top-banner-placeholder ###ad-top-leaderboard ###ad-top-left ###ad-top-right ###ad-top-right-container ###ad-top-text-low ###ad-top-wrap ###ad-top-wrapper ###ad-tower ###ad-tower1 ###ad-trailerboard-spot ###ad-two ###ad-typ1 ###ad-unit ###ad-uprrail1 ###ad-video ###ad-west ###ad-wide-leaderboard ###ad-wrap ###ad-wrap-right ###ad-wrapper ###ad-wrapper-728x90 ###ad-wrapper-left ###ad-wrapper-right ###ad-wrapper1 ###ad-yahoo-simple ###ad-zone-1 ###ad-zone-2 ###ad-zone-inline ###ad001 ###ad002 ###ad01 ###ad02 ###ad1-468x400 ###ad1-home ###ad1-wrapper ###ad1006 ###ad101 ###ad10Sp ###ad11 ###ad11Sp ###ad120x600 ###ad120x600container ###ad120x60_override ###ad125B ###ad125BL ###ad125BR ###ad125TL ###ad125TR ###ad125x125 ###ad160 ###ad160-2 ###ad160Container ###ad160Wrapper ###ad160a ###ad160x600 ###ad160x600right ###ad180 ###ad1Sp ###ad1_top-left ###ad2-home ###ad2-label ###ad2-original-placeholder ###ad250 ###ad260x60 ###ad2CONT ###ad2Sp ###ad2_footer ###ad2_iframe ###ad2_inline ###ad2gameslayer ###ad300 ###ad300-250 ###ad300-title ###ad300250top ###ad300IndexBox ###ad300X250 ###ad300_250 ###ad300_a ###ad300_x_250 ###ad300b ###ad300c ###ad300text ###ad300top ###ad300x100Middle ###ad300x150 ###ad300x250 ###ad300x250Module ###ad300x250_336x280_300x600_336x850 ###ad300x250_336x280_bottom ###ad300x250_callout ###ad300x250box ###ad300x250box2 ###ad300x250c ###ad300x50 ###ad300x60 ###ad300x600 ###ad300x600_callout ###ad31 ###ad32 ###ad330x240 ###ad336 ###ad336atf ###ad336iiatf ###ad336x280 ###ad375x85 ###ad3Article ###ad3small ###ad468 ###ad468_hidden ###ad468x60 ###ad468x60-story ###ad468x60_top ###ad470 ###ad508x125 ###ad520x85 ###ad526x250 ###ad5_inline ###ad6 ###ad600 ###ad650 ###ad720x90bot ###ad728 ###ad72890foot ###ad728Bottom ###ad728Box ###ad728BoxBtm ###ad728Header ###ad728Mid ###ad728Top ###ad728Wrapper ###ad728X90 ###ad728foot ###ad728h ###ad728top ###ad728x90 ###ad728x90_1 ###ad728x90asme ###ad728x90box ###ad76890topContainer ###ad768top1 ###ad90 ###ad97090 ###adAd ###adBadges ###adBanner ###adBanner10 ###adBanner120x600 ###adBanner160x600 ###adBanner160x610 ###adBanner2 ###adBanner3 ###adBanner336x280 ###adBanner4 ###adBanner728 ###adBanner728_bot ###adBanner9 ###adBannerBottom ###adBannerBreaking ###adBannerSpacer ###adBannerTable ###adBannerTop ###adBannerWrap ###adBannerWrapperFtr ###adBar ###adBelt ###adBlock01 ###adBlock125 ###adBlockContainer ###adBlockContent ###adBlockOverlay ###adBlockTop ###adBlocks ###adBottbanner ###adBottom ###adBox ###adBox11 ###adBox16 ###adBox350 ###adBox390 ###adBoxUpperRight ###adBrandDev ###adBreak ###adCENTRAL ###adCTXSp ###adChannel ###adChoiceFooter ###adChoices ###adChoicesIcon ###adChoicesLogo ###adCirc300X200 ###adCirc300X250 ###adCirc300x300 ###adCirc620X100 ###adCirc_620_100 ###adClickLeft ###adClickMe ###adClickRight ###adCol ###adColumn ###adColumn3 ###adCompanionBanner ###adCompanionSubstitute ###adComponentWrapper ###adContainerCC ###adContainerForum ###adContainer_1 ###adContainer_2 ###adContainer_3 ###adContent ###adContentHolder ###adContext ###adControl1 ###adDailyDeal ###adDiv ###adDiv0 ###adDiv1 ###adDiv300 ###adDiv4 ###adDiv728 ###adDivContainer ###adFiller ###adFixFooter ###adFlashDiv ###adFooter ###adFooterTitel ###adFot ###adFoxBanner ###adFps ###adFrame ###adFtofrs ###adGallery ###adGmWidget ###adGoogleText ###adGroup1 ###adGroup4 ###adHeader ###adHeaderTop ###adHeaderWrapper ###adHolder ###adHolder1 ###adHolder2 ###adHolder3 ###adHolder300x250 ###adHolder4 ###adHolder5 ###adHolder6 ###adIframe ###adInBetweenPosts ###adInCopy ###adInstoryOneWrap ###adInstoryTwoWrap ###adInteractive1 ###adInteractive4 ###adInteractiveInline ###adIsland ###adLB ###adLContain ###adLabel ###adLayer ###adLeader ###adLeaderTop ###adLeaderboard ###adLeaderboard-middle ###adLeaderboardUp ###adLeft ###adLink ###adLink1 ###adLink300 ###adLocation-1 ###adLocation-2 ###adLocation-3 ###adLocation-4 ###adLounge ###adLrec ###adMOBILETOP ###adMPU ###adMPUHolder ###adMagAd ###adMarketplace ###adMed ###adMedRect ###adMediaWidget ###adMediumRectangle ###adMeld ###adMessage ###adMid1 ###adMid2 ###adMiddle0Frontpage ###adMiddle_imgAd ###adMiniPremiere ###adMonster1 ###adMpu ###adMpuBottom ###adNshareWrap ###adOne ###adOuter ###adPLaceHolderTop728 ###adPUSHDOWNBANNER ###adPageContainer ###adPanelAjaxUpdate ###adPlaceHolder1 ###adPlaceHolder2 ###adPlaceHolderRight ###adPlacer ###adPopover ###adPosOne ###adPosition0 ###adPosition14 ###adPosition5 ###adPosition6 ###adPosition7 ###adPosition9 ###adPush ###adRContain ###adRight ###adRight1 ###adRight2 ###adRight3 ###adRight4 ###adRight5 ###adRightColumnHolder ###adSPLITCOLUMNTOPRIGHT ###adScraper ###adSense ###adSenseBottomDiv ###adSenseBox ###adSenseContentTop ###adSenseLoadingPlaceHolder ###adSenseModule ###adSenseResultAdblock ###adSenseResults ###adSenseSidebarBottom ###adSenseTall ###adSenseWrapper ###adServer_marginal ###adSet ###adShortTower ###adSideButton ###adSidebar ###adSidebarSq ###adSite ###adSkin ###adSkinBackdrop ###adSky ###adSkyPosition ###adSkyscraper ###adSlider ###adSlot-inPage-300x250-right ###adSlot01 ###adSlot02 ###adSlot2 ###adSlot3 ###adSlot4 ###adSlug ###adSpace ###adSpace0 ###adSpace1 ###adSpace10 ###adSpace11 ###adSpace12 ###adSpace13 ###adSpace14 ###adSpace15 ###adSpace16 ###adSpace17 ###adSpace18 ###adSpace19 ###adSpace2 ###adSpace20 ###adSpace21 ###adSpace22 ###adSpace23 ###adSpace24 ###adSpace25 ###adSpace3 ###adSpace300_ifrMain ###adSpace4 ###adSpace5 ###adSpace6 ###adSpace7 ###adSpace8 ###adSpace9 ###adSpaceBottom ###adSpace_footer ###adSpace_right ###adSpace_top ###adSpacer ###adSpecial ###adSplotlightEm ###adSponsor ###adSpot-Leader ###adSpot-banner ###adSpot-island ###adSpot-mrec1 ###adSpot-promobox1 ###adSpot-promobox2 ###adSpot-sponsoredlinks ###adSpot-textbox1 ###adSpot-twin ###adSpot-widestrip ###adSpotAdvertorial ###adSpotIsland ###adSpotIslandLarge ###adSpotSponsoredLinks ###adSpotholder-EGN ###adSpotlightSquare1 ###adSqb ###adSquare ###adStaticA ###adStrip ###adSuperAd ###adSuperPremiere ###adSuperSkyscraper ###adSuperbanner ###adTableCell ###adTag ###adTag-genre ###adTag1 ###adTag2 ###adTeaser ###adText ###adTextCustom ###adTextLink ###adTextRt ###adText_container ###adThree ###adTicker ###adTiff ###adTile ###adTop ###adTop1 ###adTop2 ###adTopBanner-inner ###adTopBanner1 ###adTopBox300x300 ###adTopContent ###adTopModule ###adTopbanner ###adTopboxright ###adTower ###adTower1 ###adTower2 ###adTwo ###adUn_1 ###adUn_2 ###adUn_3 ###adUnit ###adValue ###adVcss ###adWideSkyscraper ###adWrap ###adWrapper1 ###adWrapperLeft ###adWrapperRight ###adZoneTop ###ad_0 ###ad_02 ###ad_03 ###ad_04 ###ad_1 ###ad_120_sidebar ###ad_120x600 ###ad_120x90 ###ad_130x250_inhouse ###ad_160 ###ad_160_600 ###ad_160_600_2 ###ad_160_container_left ###ad_160_container_right ###ad_160_sidebar ###ad_160x160 ###ad_160x600 ###ad_175x300 ###ad_190x90 ###ad_2 ###ad_250 ###ad_250x250 ###ad_3 ###ad_300 ###ad_300_250 ###ad_300_250_1 ###ad_300_250_inline ###ad_300_container ###ad_300_interruptor ###ad_300_wrapper ###ad_300a ###ad_300b ###ad_300c ###ad_300misc ###ad_300x100 ###ad_300x100_m_c ###ad_300x250 ###ad_300x250Ando ###ad_300x250_1 ###ad_300x250_2 ###ad_300x250_container ###ad_300x250_content_column ###ad_300x250_m_c ###ad_300x250_secondary ###ad_300x250_startgame ###ad_300x250m ###ad_300x600 ###ad_300x90 ###ad_336 ###ad_350_200 ###ad_4 ###ad_450x280 ###ad_468_60 ###ad_468x120 ###ad_468x60 ###ad_470x60a ###ad_5 ###ad_500 ###ad_500_label ###ad_500x150 ###ad_6 ###ad_700_90 ###ad_700x430 ###ad_728 ###ad_728_90 ###ad_728_foot ###ad_728_holder ###ad_728a ###ad_728b ###ad_728x90 ###ad_728x90_container ###ad_728x90_content ###ad_728x90home ###ad_728x91 ###ad_8 ###ad_88x31 ###ad_940 ###ad_984 ###ad_990x90 ###ad_A ###ad_B ###ad_B1 ###ad_Banner ###ad_Bottom ###ad_C ###ad_C2 ###ad_D ###ad_DisplayAd1 ###ad_DisplayAd2 ###ad_E ###ad_Entry_160x600 ###ad_Entry_728x90 ###ad_F ###ad_G ###ad_H ###ad_Home_300x250 ###ad_I ###ad_J ###ad_K ###ad_L ###ad_LargeRec01 ###ad_M ###ad_Middle ###ad_Middle1 ###ad_N ###ad_NorthBanner ###ad_O ###ad_P ###ad_Position1 ###ad_Pushdown ###ad_R1 ###ad_Right ###ad_Top ###ad_Top2 ###ad_TopLongBanner ###ad_Wrap ###ad_YieldManager-160x600 ###ad_YieldManager-300x250 ###ad_YieldManager-728x90 ###ad_above_game ###ad_ad ###ad_adsense ###ad_after_navbar ###ad_anchor ###ad_and_content_ad_box ###ad_area ###ad_article_btm ###ad_banner ###ad_bannerManage_1 ###ad_banner_1 ###ad_banner_120x600 ###ad_banner_125x300 ###ad_banner_300x250 ###ad_banner_468x60 ###ad_banner_728x90 ###ad_banner_728x90_bot ###ad_banner_bot ###ad_banner_example ###ad_banner_top ###ad_banners ###ad_banners_content ###ad_bar ###ad_bar_rect ###ad_bellow_post ###ad_bg ###ad_bg_image ###ad_big ###ad_bigbox ###ad_bigbox_companion ###ad_bigrectangle ###ad_bigsize_wrapper ###ad_billboard ###ad_billboard2 ###ad_billboard_ifm ###ad_block ###ad_block_0 ###ad_block_1 ###ad_block_2 ###ad_block_300x250 ###ad_block_mpu ###ad_board_after_forums ###ad_board_before_forums ###ad_body ###ad_bottom ###ad_bottom_1x1 ###ad_bottom_728x90 ###ad_bottom_another ###ad_bottom_article_text ###ad_bottombrandtext ###ad_box ###ad_box02 ###ad_box160a ###ad_box_2 ###ad_box_ad_0 ###ad_box_ad_1 ###ad_box_colspan ###ad_box_top ###ad_branding ###ad_bs_area ###ad_bucket_med_rectangle_1 ###ad_bucket_med_rectangle_2 ###ad_buttons ###ad_category_middle ###ad_cell ###ad_center ###ad_center_monster ###ad_channel ###ad_chitikabanner_120x600LH ###ad_choices ###ad_circ300x250 ###ad_circ_300_200 ###ad_circ_300x250 ###ad_circ_300x300 ###ad_close ###ad_cna2 ###ad_comments ###ad_companion_banner ###ad_complex ###ad_comps_top ###ad_cont ###ad_cont1 ###ad_cont2 ###ad_container ###ad_container_0 ###ad_container_300x250 ###ad_container_marginal ###ad_container_side ###ad_container_sidebar ###ad_container_top ###ad_content ###ad_content_before_first_para ###ad_content_fullsize ###ad_content_primary ###ad_content_right ###ad_content_top ###ad_content_wrap ###ad_creative_2 ###ad_creative_3 ###ad_creative_5 ###ad_cyborg ###ad_display_300_250 ###ad_display_728_90 ###ad_div ###ad_div_bottom ###ad_div_top ###ad_embed_300x250 ###ad_fb_circ ###ad_feature ###ad_feedback ###ad_fg ###ad_firstpost ###ad_flyrelax ###ad_foot ###ad_footer ###ad_footer1 ###ad_footerAd ###ad_footer_s ###ad_footer_small ###ad_frame ###ad_frame1 ###ad_front_three ###ad_fullbanner ###ad_gallery ###ad_gallery_bot ###ad_global_300x250 ###ad_global_above_footer ###ad_global_header ###ad_global_header1 ###ad_global_header2 ###ad_google_content336 ###ad_googlebanner_160x600LH ###ad_grp1 ###ad_grp2 ###ad_gutter_top ###ad_h3 ###ad_haha_1 ###ad_haha_4 ###ad_halfpage ###ad_hdr_2 ###ad_head ###ad_header ###ad_header_1 ###ad_header_container ###ad_header_logo_placeholder ###ad_headerlarge ###ad_help_link_new ###ad_hf ###ad_hide_for_menu ###ad_holder ###ad_home ###ad_home_middle ###ad_horizontal ###ad_horseshoe_left ###ad_horseshoe_right ###ad_horseshoe_spacer ###ad_horseshoe_top ###ad_hotpots ###ad_houseslot1_desktop ###ad_iframe_160_by_600_middle ###ad_iframe_300 ###ad_img ###ad_img_banner ###ad_in_arti ###ad_infoboard_box ###ad_inplace_1 ###ad_interestmatch ###ad_interestmatch400 ###ad_island ###ad_island2 ###ad_island_incontent ###ad_island_incontent2 ###ad_keywrods ###ad_label ###ad_large ###ad_large_rectangular ###ad_lastpost ###ad_layer ###ad_layer1 ###ad_layer2 ###ad_ldb ###ad_lead1 ###ad_leader ###ad_leaderBoard ###ad_leaderboard ###ad_leaderboard728x90 ###ad_leaderboard_1 ###ad_leaderboard_flex ###ad_leaderboard_master ###ad_leaderboard_middle ###ad_leaderboard_top ###ad_leaderboardtwo ###ad_leaderborder_container1 ###ad_left ###ad_left_1 ###ad_left_2 ###ad_left_3 ###ad_left_skyscraper ###ad_left_skyscraper_2 ###ad_left_top ###ad_lft ###ad_link ###ad_links ###ad_links_footer ###ad_lnk ###ad_lrec ###ad_lwr_square ###ad_main ###ad_marker ###ad_mast ###ad_med_rect ###ad_medium ###ad_medium_rectangle ###ad_medium_rectangular ###ad_mediumrectangle ###ad_megabanner ###ad_menu_header ###ad_message ###ad_messageboard_x10 ###ad_middle ###ad_middle_122 ###ad_middle_2 ###ad_middle_bottom ###ad_midstrip ###ad_ml ###ad_module ###ad_most_pop_234x60_req_wrapper ###ad_mpu ###ad_mpu2 ###ad_mpu300x250 ###ad_mpu_1 ###ad_mpuav ###ad_mrcontent ###ad_mrec ###ad_myFrame ###ad_netpromo ###ad_new ###ad_newsletter ###ad_num_1 ###ad_num_2 ###ad_num_3 ###ad_one ###ad_overlay ###ad_overlay_countdown ###ad_overture ###ad_panel ###ad_pencil ###ad_ph_1 ###ad_place ###ad_placeholder ###ad_play_300 ###ad_plugs ###ad_post ###ad_post_300 ###ad_poster ###ad_pr_info ###ad_primary ###ad_primaryAd ###ad_promoAd ###ad_publicidad ###ad_pushupbar-closed ###ad_rail ###ad_rect ###ad_rect1 ###ad_rect2 ###ad_rect3 ###ad_rect_body ###ad_rect_bottom ###ad_rect_c ###ad_rectangle ###ad_rectangle_medium ###ad_rectangular ###ad_region1 ###ad_region2 ###ad_region3 ###ad_region5 ###ad_related_links_div ###ad_related_links_div_program ###ad_replace_div_0 ###ad_replace_div_1 ###ad_report_leaderboard ###ad_report_rectangle ###ad_results ###ad_right ###ad_right3 ###ad_rightSidebarFirstBanner ###ad_rightSidebarSecondBanner ###ad_right_1 ###ad_right_box ###ad_right_column1_1 ###ad_right_column2_1 ###ad_right_content_article_page ###ad_right_content_home ###ad_right_main ###ad_right_out ###ad_right_rail_bottom ###ad_right_rail_flex ###ad_right_rail_top ###ad_right_second ###ad_right_skyscraper ###ad_right_skyscraper_2 ###ad_right_top ###ad_righttop-300x250 ###ad_ros_tower ###ad_rotator-2 ###ad_rotator-3 ###ad_row ###ad_row_home ###ad_rr_1 ###ad_rside ###ad_rside_link ###ad_script_head ###ad_sec ###ad_sec_div ###ad_secondary ###ad_sense ###ad_sense_help ###ad_sgd ###ad_short ###ad_sidebar ###ad_sidebar1 ###ad_sidebar2 ###ad_sidebar3 ###ad_sidebar_1 ###ad_sidebar_top ###ad_silo ###ad_sitebar ###ad_skin ###ad_sky ###ad_sky1 ###ad_sky2 ###ad_sky3 ###ad_skyscraper ###ad_skyscraper160x600 ###ad_skyscraper_1 ###ad_skyscraper_right ###ad_skyscraper_text ###ad_slot ###ad_slot_bottom ###ad_slot_leaderboard ###ad_slot_livesky ###ad_slot_right_bottom ###ad_slot_right_top ###ad_slot_sky_top ###ad_small ###ad_space ###ad_space_300_250 ###ad_space_728 ###ad_space_top ###ad_sponsored ###ad_sponsorship_2 ###ad_spot300x250 ###ad_spot_a ###ad_spot_b ###ad_spotlight ###ad_square ###ad_squares ###ad_ss ###ad_stck ###ad_strapad ###ad_stream10 ###ad_stream11 ###ad_stream12 ###ad_stream16 ###ad_stream17 ###ad_stream19 ###ad_stream8 ###ad_strip ###ad_table ###ad_takeover ###ad_tbl ###ad_term_bottom_place ###ad_text:not(textarea) ###ad_thread_first_post_content ###ad_thread_last_post_content ###ad_tile_home ###ad_top ###ad_topBanner ###ad_top_728x90 ###ad_top_banner ###ad_top_bar ###ad_top_header_center ###ad_top_holder ###ad_topbanner ###ad_topmob ###ad_topnav ###ad_tp_banner_1 ###ad_tp_banner_2 ###ad_two ###ad_txt ###ad_under_game ###ad_unit ###ad_unit2 ###ad_vertical ###ad_video_abovePlayer ###ad_video_belowPlayer ###ad_video_large ###ad_website_top ###ad_wide ###ad_wide_box ###ad_widget ###ad_widget_1 ###ad_window ###ad_wp_base ###ad_wrap ###ad_wrapper ###ad_wrapper1 ###ad_wrapper2 ###ad_x10 ###ad_x20 ###ad_zone ###ad_zone1 ###ad_zone2 ###ad_zone3 ###adamazonbox ###adaptv_ad_player_div ###adaptvcompanion ###adbForum ###adbackground ###adbanner ###adbanner-home-left ###adbanner-home-right ###adbanner-middle ###adbanner-top-left ###adbanner-top-right ###adbanner00001 ###adbanner00002 ###adbanner00003 ###adbanner00004 ###adbanner00005 ###adbanner1 ###adbanner_abovethefold_300 ###adbannerbox ###adbannerdiv ###adbannerleft ###adbannerright ###adbannerwidget ###adbar ###adbar_ad_1_div ###adbar_ad_2_div ###adbar_ad_3_div ###adbar_ad_4_div ###adbar_ads_container_div ###adbar_main_div ###adbarbox ###adbard ###adbg_ad_0 ###adbg_ad_1 ###adbig ###adblade ###adbladeSp ###adblade_ad ###adblock ###adblock-300x250 ###adblock-big ###adblock-jango ###adblock-leaderboard ###adblock-small ###adblock1 ###adblock2 ###adblock4 ###adblock_header_ad_1 ###adblock_header_ad_1_inner ###adblock_sidebar_ad_2 ###adblock_sidebar_ad_2_inner ###adblock_v ###adblockbottom ###adblockerMess ###adblockerwarnung ###adblockrighta ###adblocktop ###adblocktwo ###adbn ###adbn_UMU ###adbnr ###adboard ###adbody ###adbottom ###adbottomgao ###adbox ###adbox-indivisual-body-topright ###adbox-placeholder-topbanner ###adbox-topbanner ###adbox1 ###adbox2 ###adbox300600 ###adbox300x250_1 ###adbox300x250_2 ###adbox_right ###adbrite ###adbrite_inline_div ###adbritebottom ###adbutton ###adbuttons ###adcarousel ###adcatfish ###adcell ###adcenter ###adcenter2 ###adcenter4 ###adchoices-icon ###adchoices_container ###adclear ###adclose ###adcode ###adcode1 ###adcode10 ###adcode2 ###adcode3 ###adcode4 ###adcolContent ###adcolumn ###adcolumnwrapper ###adcontainer ###adcontainer1 ###adcontainer125px ###adcontainer2 ###adcontainer250x250 ###adcontainer3 ###adcontainer5 ###adcontainerRight ###adcontainer___gelement_adbanner_2_0 ###adcontainer_top_ads ###adcontainsm ###adcontent ###adcontent1 ###adcontextlinks ###adcontrolPushSite ###adcontrolhalfbanner ###adcontrolisland ###add-top ###add720 ###add_160x600 ###add_720bottom ###add_block_ad1 ###add_block_ad2 ###add_ciao2 ###add_space_google ###add_space_sidebar ###addbottomleft ###addiv-bottom ###addiv-top ###addspaceleft ###addspaceright ###adfactor-label ###adfloat ###adfooter ###adfooter_728x90 ###adfooter_hidden ###adframe:not(frameset) ###adframetop ###adfreead ###adhalfbanner_wrapper ###adhalfpage ###adhead ###adhead_g ###adheader ###adheadhubs ###adhide ###adholder ###adhome ###adhomepage ###adhzh ###adid10601 ###adid2161 ###adiframe1_iframe ###adiframe2_iframe ###adiframe3_iframe ###adigniter ###adimg ###adimg0 ###adimg1 ###adimg3 ###adimg6 ###adition_content_ad ###adjacency ###adjs_id ###adkit_content-block ###adkit_content-foot ###adkit_footer ###adkit_mrec1 ###adkit_mrec2 ###adkit_rectangle ###adkit_rnav-bt ###adkit_rnav-fb ###adl_120x600 ###adl_250x250 ###adl_300x100 ###adl_300x120 ###adl_300x250 ###adl_300x250_td ###adl_728x90 ###adl_individual_1 ###adl_leaderboard ###adl_medium_rectangle ###adlabel ###adlabelFooter ###adlanding ###adlandscape ###adlargeverti ###adlargevertimarginauto ###adlayer ###adlayerContainer ###adlayer_back ###adlayerad ###adleaderboard ###adleaderboard_flex ###adleaderboardb ###adleaderboardb_flex ###adleft ###adlink-13 ###adlink-133 ###adlink-19 ###adlink-197 ###adlink-213 ###adlink-28 ###adlink-55 ###adlink-74 ###adlink-98 ###adlinks ###adlinkws ###adlove ###adlrec ###admain ###admanagerResultListBox ###admanager_leaderboard ###admanager_top_banner ###admid ###admiddle3 ###admiddle3center ###admiddle3left ###admiddleCenter ###admod2 ###admon-300x250 ###admon-728x90 ###admulti520 ###adnet ###adnews ###adnorth ###adops_cube ###adops_leaderboard ###adops_skyscraper ###adoptionsimg ###adoverlaysrc ###adpanel-block ###adplace ###adplaceholder_mpu01 ###adplacement ###adplacer_preroll1 ###adplate-content ###adpos-top ###adpos1-leaderboard ###adposition ###adposition-C ###adposition-FPMM ###adposition-REM2 ###adposition-SHADE ###adposition-TOCSS ###adposition-TVSP ###adposition-inner-REM1 ###adposition-inner-REM3 ###adposition1 ###adposition10 ###adposition1_container ###adposition2 ###adposition3 ###adposition4 ###adpositionbottom ###adpostloader ###adpromo ###adprovider-default ###adrect ###adrectangle ###adrectanglea ###adrectanglea_flex ###adrectanglea_hidden ###adrectangleb ###adrectangleb_flex ###adrectmarginauto ###adrig ###adright ###adright2 ###adrightbottom ###adrighthome ###adrightrail ###adriver_middle ###adriver_top ###adrotate_widgets-11 ###adrotate_widgets-12 ###adrotate_widgets-2 ###adrotate_widgets-20 ###adrotate_widgets-24 ###adrotate_widgets-3 ###adrotate_widgets-4 ###adrotate_widgets-5 ###adrotate_widgets-6 ###adrotate_widgets-7 ###adrow ###adrow-house ###adrow1 ###adrow3 ###ads-1 ###ads-125 ###ads-160x600 ###ads-200 ###ads-200x200-a ###ads-250 ###ads-300 ###ads-300-250 ###ads-336x280 ###ads-468 ###ads-5 ###ads-728x90 ###ads-A ###ads-B ###ads-B1 ###ads-C ###ads-C1 ###ads-E ###ads-E1 ###ads-F ###ads-G ###ads-H ###ads-K ###ads-area ###ads-banner ###ads-block ###ads-bot ###ads-bottom ###ads-box-header-pb ###ads-by-google ###ads-category ###ads-col ###ads-contain-125 ###ads-container-2 ###ads-container-anchor ###ads-container-top ###ads-dell ###ads-dw ###ads-footer ###ads-footer-inner ###ads-footer-wrap ###ads-google ###ads-h-left ###ads-h-right ###ads-header ###ads-header-728 ###ads-horizontal ###ads-hoster-2 ###ads-indextext ###ads-king ###ads-leader ###ads-leaderboard ###ads-leaderboard1 ###ads-left-top ###ads-lrec ###ads-main ###ads-menu ###ads-middle ###ads-mn ###ads-mpu ###ads-outer ###ads-panel ###ads-prices ###ads-rhs ###ads-right ###ads-right-bottom ###ads-right-cube ###ads-right-skyscraper ###ads-right-top ###ads-right-twobottom ###ads-rt ###ads-sidebar-skyscraper-unit ###ads-slot ###ads-sponsored-boxes ###ads-sticky ###ads-text ###ads-top ###ads-tp ###ads-under-rotator ###ads-vers7 ###ads-vertical ###ads-vertical-wrapper ###ads-wrap ###ads-wrapper ###ads100Box ###ads100Middlei4 ###ads120 ###ads120_600-widget-2 ###ads125 ###ads160_600-widget-3 ###ads160_600-widget-5 ###ads160_600-widget-7 ###ads160left ###ads2 ###ads250_250-widget-2 ###ads300 ###ads300-250 ###ads300Bottom ###ads300Top ###ads300_250-widget-10 ###ads300_250-widget-11 ###ads300_250-widget-2 ###ads300_250-widget-3 ###ads300_250-widget-4 ###ads300_250-widget-6 ###ads300hp ###ads300k ###ads300x200 ###ads300x250 ###ads300x250_2 ###ads300x250_single ###ads315 ###ads336Box ###ads336x280 ###ads7 ###ads728 ###ads72890top ###ads728bottom ###ads728top ###ads728x90 ###ads728x90_2 ###ads790 ###adsBannerFrame ###adsBar ###adsBottom ###adsBox-460_left ###adsBox-dynamic-right ###adsBoxResultsPage ###adsCTN ###adsContainer ###adsContent ###adsDisplay ###adsDiv0 ###adsDiv1 ###adsDiv2 ###adsDiv3 ###adsDiv4 ###adsDiv5 ###adsDiv6 ###adsDiv7 ###adsGooglePos ###adsHeader ###adsHeading ###adsID ###adsIframe ###adsIfrme1 ###adsIfrme2 ###adsIfrme3 ###adsIfrme4 ###adsLREC ###adsLeftZone1 ###adsLeftZone2 ###adsLinkFooter ###adsNarrow ###adsPanel ###adsProdHighlight_wrap ###adsSPRBlock ###adsSuperCTN ###adsTop ###adsTopLeft ###adsZone1 ###adsZone2 ###adsZone_1 ###ads_01 ###ads_120x60_block ###ads_160 ###ads_3 ###ads_300 ###ads_300x250 ###ads_320_260 ###ads_320_260_2 ###ads_728 ###ads_728x90 ###ads_absolute_left ###ads_absolute_right ###ads_back ###ads_banner ###ads_banner1 ###ads_banner_header ###ads_banner_right1 ###ads_bar ###ads_belowforumlist ###ads_belownav ###ads_big ###ads_bigrec1 ###ads_bigrec2 ###ads_bigrec3 ###ads_block ###ads_bottom ###ads_bottom_inner ###ads_bottom_outer ###ads_box ###ads_box1 ###ads_box2 ###ads_box_bottom ###ads_box_right ###ads_box_top ###ads_button ###ads_by_google ###ads_campaign ###ads_catDiv ###ads_center ###ads_center_banner ###ads_central ###ads_container ###ads_dynamicShowcase ###ads_eo ###ads_expand ###ads_footer ###ads_fullsize ###ads_h ###ads_halfsize ###ads_header ###ads_header_games ###ads_horiz ###ads_horizontal ###ads_html1 ###ads_html2 ###ads_im ###ads_inner ###ads_insert_container ###ads_layout_bottom ###ads_lb ###ads_lb_frame ###ads_leaderbottom ###ads_left_top ###ads_line ###ads_mads_r1 ###ads_mads_r2 ###ads_medrect ###ads_notice ###ads_pave ###ads_place ###ads_player ###ads_player_audio ###ads_player_line ###ads_postdownload ###ads_pro_468_60_on_vid ###ads_r_c ###ads_right ###ads_right_sidebar ###ads_right_top ###ads_section_textlinks ###ads_side ###ads_sidebar_bgnd ###ads_sidebar_roadblock ###ads_sky ###ads_slide_div ###ads_space ###ads_space_header ###ads_special_center ###ads_sponsFeed-headline ###ads_sponsFeed-left ###ads_sponsored_link_pixel ###ads_superbanner1 ###ads_superbanner2 ###ads_superior ###ads_td ###ads_text ###ads_textlinks ###ads_title ###ads_top ###ads_top2 ###ads_top_banner ###ads_top_container ###ads_top_right ###ads_top_sec ###ads_topbanner ###ads_tower1 ###ads_video ###ads_watch_top_square ###ads_wide ###ads_wrapper ###ads_zone27 ###adsbottom ###adsbottombluesleft ###adsbox ###adsbox-left ###adsbox-right ###adsbox1 ###adsbox2 ###adsbox3 ###adsbox336x280 ###adsbox4 ###adsbox728x90 ###adscenter ###adscolumn ###adscontainer ###adscontent ###adsctl00_AdsHome2 ###adsd_contentad_r1 ###adsd_contentad_r2 ###adsd_contentad_r3 ###adsd_topbanner ###adsd_txt_sky ###adsdaq160600 ###adsdaq300250 ###adsdaq72890 ###adsdiv ###adsdiv300 ###adsdiv468 ###adsdiv_close ###adsection ###adsense ###adsense-2 ###adsense-468x60 ###adsense-area ###adsense-bottom ###adsense-end-300 ###adsense-header ###adsense-letterbox ###adsense-link ###adsense-middle ###adsense-module-bottom ###adsense-new ###adsense-post ###adsense-right ###adsense-sidebar ###adsense-tag ###adsense-text ###adsense-top ###adsense-wrap ###adsense03 ###adsense04 ###adsense05 ###adsense1 ###adsense160600 ###adsense2 ###adsense2pos ###adsense300x250 ###adsense468 ###adsense6 ###adsense728 ###adsenseArea ###adsenseHeader ###adsenseLeft ###adsenseOne ###adsenseWrap ###adsense_300x250 ###adsense_article_bottom ###adsense_article_left ###adsense_banner_top ###adsense_block ###adsense_block_238x200 ###adsense_block_350x320 ###adsense_bottom_ad ###adsense_box ###adsense_box2 ###adsense_box_video ###adsense_honeytrap ###adsense_image ###adsense_inline ###adsense_item_detail ###adsense_leaderboard ###adsense_overlay ###adsense_placeholder_2 ###adsense_sidebar ###adsense_testa ###adsense_top ###adsense_unit5 ###adsense_ziel ###adsensebreadcrumbs ###adsenseheader ###adsensehorizontal ###adsensempu ###adsensepo ###adsensepos ###adsensequadr ###adsenseskyscraper ###adsensetext ###adsensetopmobile ###adsensetopplay ###adsensewide ###adsensewidget-3 ###adserv ###adserve-Banner ###adserve-Leaderboard ###adserve-MPU ###adserve-Sky ###adsfundo ###adshometop ###adshowbtm ###adshowtop ###adside ###adsideblock1 ###adsider ###adsiframe ###adsimage ###adskinleft ###adskinlink ###adskinright ###adskintop ###adsky ###adskyleftdiv ###adskyrightdiv ###adskyscraper ###adskyscraper_flex ###adsleft1 ###adslist ###adslistbox ###adslot ###adslot-2-container ###adslot-3-container ###adslot-4-container ###adslot1 ###adslot1173 ###adslot1189 ###adslot1202 ###adslot2 ###adslot3 ###adslot_c2 ###adslot_m1 ###adslot_m2 ###adslot_m3 ###adsmiddle ###adsonar ###adsonarBlock ###adspace ###adspace-1 ###adspace-2 ###adspace-300x250 ###adspace-728 ###adspace-728x90 ###adspace-bottom ###adspace-leaderboard-top ###adspace-one ###adspace-panorama ###adspace-top ###adspace300x250 ###adspaceBox ###adspaceBox300 ###adspaceBox300_150 ###adspaceBox300white ###adspaceRow ###adspace_header ###adspace_leaderboard ###adspace_top ###adspacer ###adspan ###adspdl-container ###adspecial_offer_box ###adsplace1 ###adsplace2 ###adsplace4 ###adsplash ###adsponsorImg ###adsponsored_links_box ###adspot ###adspot-1 ###adspot-149x170 ###adspot-1x4 ###adspot-2 ###adspot-295x60 ###adspot-2a ###adspot-2b ###adspot-300x110-pos-1 ###adspot-300x125 ###adspot-300x250-pos-1 ###adspot-300x250-pos-2 ###adspot-300x250-pos1 ###adspot-300x600-pos1 ###adspot-468x60-pos-2 ###adspot-620x270-pos-1 ###adspot-620x45-pos-1 ###adspot-620x45-pos-2 ###adspot-728x90 ###adspot-728x90-pos-2 ###adspot-a ###adspot-bottom ###adspot-c ###adspot-d ###adspot-top ###adspot300x250 ###adspot_220x90 ###adspot_300x250 ###adspot_468x60 ###adspot_728x90 ###adspotlight1 ###adsquare ###adsquare2 ###adsright ###adss ###adssidebar2 ###adssidebar3 ###adsspace ###adstd ###adstext2 ###adstop ###adstory ###adstrip ###adstripbottom ###adstripnew ###adstuff ###adswidget1-quick-adsense ###adswidget2-quick-adsense ###adswizzBanner ###adsxpls2 ###adszed-728x90 ###adtab ###adtab-feedback2 ###adtable_top ###adtag5 ###adtag8 ###adtag_right_side ###adtagfooter ###adtagheader ###adtagrightcol ###adtags_left ###adtaily ###adtaily-widget-light ###adtech_0 ###adtech_1 ###adtech_2 ###adtech_3 ###adtech_728or920_2 ###adtech_googleslot_03c ###adtech_leaderboard01 ###adtech_takeover ###adtechbanner728 ###adtext ###adtext-top-content ###adtop ###adtopHeader ###adtop_dfp ###adtopbanner ###adtopbox ###adtophp ###adtrafficright ###adtxt ###adunderpicture ###adunit ###adunit300x500 ###adunit_video ###adunitl ###adv-01 ###adv-300 ###adv-box ###adv-companion-iframe ###adv-container ###adv-ext-ext-1 ###adv-ext-ext-2 ###adv-fb-container ###adv-google ###adv-leaderboard ###adv-left ###adv-masthead ###adv-middle ###adv-middle1 ###adv-midroll ###adv-mpux ###adv-preroll ###adv-right ###adv-right1 ###adv-strip ###adv-text ###adv-title ###adv-top ###adv-x34 ###adv-x35 ###adv-x36 ###adv-x37 ###adv-x38 ###adv-x39 ###adv-x40 ###adv130x195 ###adv160x600 ###adv170 ###adv2_ban ###adv300bottom ###adv300top ###adv300x250 ###adv300x250container ###adv3_ban ###adv468x90 ###adv728 ###adv728x90 ###adv768x90 ###advCarrousel ###advHome ###advMegaBanner ###advRectangle ###advRectangle1 ###advSidebarDocBox ###advSkin ###advTop ###advTopRight_anchor ###advWrapper ###adv_300 ###adv_300x250_1 ###adv_300x250_2 ###adv_300x250_3 ###adv_468x60_content ###adv_5 ###adv_52 ###adv_6 ###adv_62 ###adv_65 ###adv_7 ###adv_70 ###adv_71 ###adv_728 ###adv_728x90 ###adv_73 ###adv_94 ###adv_96 ###adv_97 ###adv_98 ###adv_Reload ###adv_Skin ###adv_banner_featured ###adv_banner_sidebar ###adv_bootom ###adv_border ###adv_box_a ###adv_center ###adv_config ###adv_contents ###adv_contents_tem ###adv_google_300 ###adv_google_728 ###adv_halfpage ###adv_halfpage_title ###adv_holder ###adv_leaderboard ###adv_mpu1 ###adv_mpu2 ###adv_network ###adv_overlay ###adv_overlay_content ###adv_r ###adv_right ###adv_skin ###adv_sky ###adv_sponsorRowFooter ###adv_sponsorRowHeader ###adv_sponsor_cat ###adv_textlink ###adv_textual_google_div ###adv_top ###adv_top_banner_wrapper ###adv_videobox ###adv_wallpaper ###adv_wallpaper2 ###adv_wideleaderboard ###adver ###adver-top ###adver1 ###adver2 ###adver3 ###adver4 ###adver5 ###adver6 ###adver7 ###adverFrame ###advert-1 ###advert-120 ###advert-2 ###advert-ahead ###advert-banner ###advert-banner-wrap ###advert-block ###advert-boomer ###advert-box ###advert-column ###advert-container-top ###advert-display ###advert-footer ###advert-footer-hidden ###advert-header ###advert-hpu ###advert-island ###advert-leaderboard ###advert-left ###advert-links-bottom ###advert-mpu ###advert-right ###advert-right-not-home ###advert-sky ###advert-skyscaper ###advert-skyscraper ###advert-stickysky ###advert-text ###advert-top ###advert-top-banner ###advert-wrapper ###advert1 ###advert1hp ###advert2 ###advert234_container ###advert2area ###advert2areasmall ###advert3area ###advert3areasmall ###advertBanner ###advertBox ###advertBoxRight ###advertBoxSquare ###advertColumn ###advertContainer ###advertControl4_advertLink ###advertCover ###advertDB ###advertMarkerHorizontalConatiner ###advertMarkerVerticalConatiner ###advertRight ###advertSection ###advertSeparator ###advertTopLarge ###advertTopSmall ###advertTower ###advert_01 ###advert_04 ###advert_05 ###advert_07 ###advert_1 ###advert_125x125 ###advert_250x250 ###advert_300x2502 ###advert_300x2503 ###advert_561_01 ###advert_561_02 ###advert_561_03 ###advert_561_04_container ###advert_561_04_left_end ###advert_561_04_right_end ###advert_561_05 ###advert_561_07 ###advert_back_160x600 ###advert_back_300x250_1 ###advert_back_300x250_2 ###advert_banner ###advert_belowmenu ###advert_bottom_100x70 ###advert_box ###advert_container ###advert_header ###advert_home01 ###advert_home02 ###advert_home03 ###advert_home04 ###advert_leaderboard ###advert_lrec_format ###advert_media ###advert_mid ###advert_mpu ###advert_mpu_1 ###advert_mpu_2 ###advert_right_skyscraper ###advert_sky ###advert_top ###advert_yell ###advertblock ###advertborder ###advertbox2 ###advertbox3 ###advertbox4 ###adverthome ###adverti ###advertise ###advertise-here ###advertise-here-sidebar ###advertise-now ###advertise-sidebar ###advertise1 ###advertiseBanner ###advertiseGoogle ###advertiseHere ###advertiseLink ###advertise_top ###advertisediv ###advertiseheretop ###advertisement-300x250 ###advertisement-728x90 ###advertisement-content ###advertisement-detail1 ###advertisement-detail2 ###advertisement-large ###advertisement-text ###advertisement1 ###advertisement160x600 ###advertisement2 ###advertisement3 ###advertisement728x90 ###advertisementArea ###advertisementBottomThreadUser ###advertisementDIV2 ###advertisementFooterTop ###advertisementHeaderBottom ###advertisementHorizontal ###advertisementLigatus ###advertisementPrio2 ###advertisementRight ###advertisementRightcolumn0 ###advertisementRightcolumn1 ###advertisementThread ###advertisementTop ###advertisement_banner ###advertisement_block ###advertisement_box ###advertisement_container ###advertisement_label ###advertisement_notice ###advertisementblock1 ###advertisementblock2 ###advertisementblock3 ###advertisements_bottom ###advertisements_sidebar ###advertisements_top ###advertisementsarticle ###advertisementsxml ###advertiser-container ###advertiserLinks ###advertiserReports ###advertisers-caption ###advertisetop ###advertising-160x600 ###advertising-300x250 ###advertising-728x90 ###advertising-banner ###advertising-caption ###advertising-container ###advertising-control ###advertising-mockup ###advertising-skyscraper ###advertising-top ###advertising2 ###advertising3 ###advertisingBlocksLeaderboard ###advertisingBottomFull ###advertisingHrefTop ###advertisingLeftLeft ###advertisingLink ###advertisingModule160x600 ###advertisingModule728x90 ###advertisingRightColumn ###advertisingRightRight ###advertisingTop ###advertisingTopWrapper ###advertising_btm ###advertising_column ###advertising_container ###advertising_contentad ###advertising_header ###advertising_holder ###advertising_horiz_cont ###advertising_iab ###advertising_top_container ###advertising_wrapper ###advertisment-block-1 ###advertisment-horizontal ###advertisment1 ###advertismentBottom728x90_ ###advertismentElementInUniversalbox ###advertisment_content ###advertisment_panel ###advertismentgoogle ###advertistop_td ###advertleft ###advertorial ###advertorial-box ###advertorial-wrap ###advertorial1 ###advertorial_block_3 ###advertorial_links ###advertorial_red_listblock ###adverts ###adverts-top-container ###adverts-top-left ###adverts-top-middle ###adverts-top-right ###adverts_right ###advertscroll ###advertsingle ###advertspace ###advertssection ###adverttop ###advetisement_300x250 ###advframe ###advgeoul ###advgoogle ###advman-2 ###advsingle ###advt ###advt-right-skyscraper ###advt_bottom ###advtbar ###advtext ###advtop ###advtopright ###advx3_banner ###adwhitepaperwidget ###adwidget ###adwidget-5 ###adwidget-6 ###adwidget1 ###adwidget2 ###adwidget2_hidden ###adwidget3_hidden ###adwidget_hidden ###adwin ###adwin_rec ###adwith ###adwords-4-container ###adwords-box ###adwrap-295x295 ###adwrap-722x90 ###adwrap-729x90 ###adwrap-966x90 ###adwrapper ###adxBigAd ###adxBigAd2 ###adxLeaderboard ###adxMiddle ###adxMiddle5 ###adxMiddleRight ###adxSponLink ###adxSponLink2 ###adxSponLinkA ###adxToolSponsor ###adx_ad ###adx_ad_bottom ###adx_ad_bottom_close ###adxtop ###adxtop2 ###adzbanner ###adzerk ###adzerk1 ###adzerk2 ###adzerk_by ###adzone ###adzone-middle1 ###adzone-middle2 ###adzone-right ###adzone-sidebarSmallPromo1 ###adzone-sidebarSmallPromo2 ###adzone-top ###adzoneBANNER ###adzone_content ###adzonebanner ###adzoneheader ###aetn_3tier_ad_bar ###af_ad_large ###af_ad_small ###af_adblock ###afc-container ###affiliate_ad ###affinityBannerAd ###after-content-ad ###after-content-ads ###after-header-ad-left ###after-header-ad-right ###after-header-ads ###after_ad ###afterpostad ###agencies_ad ###agi-ad300x250 ###agi-ad300x250overlay ###agi-sponsored ###alert_ads ###amazon-ads ###amazon_bsa_block ###ami_ad_cntnr ###amsSparkleAdFeedback ###analytics_ad ###analytics_banner ###anchorAd ###annoying_ad ###annoying_extra_ad_wrapper ###ap-widget-ad ###ap-widget-ad-label ###ap_adframe ###ap_adtext ###ap_cu_overlay ###ap_cu_wrapper ###apiBackgroundAd ###apiTopAdContainer ###apiTopAdWrap ###apmNADiv ###apolload ###app_advertising_pregame_content ###app_advertising_rectangle ###app_advertising_rectangle_ph ###apt-homebox-ads ###araHealthSponsorAd ###area-adcenter ###area-left-ad ###area13ads ###area1ads ###article-ad ###article-ad-container ###article-advert ###article-agora-ad ###article-bottom-ad ###article-box-ad ###article-footer-sponsors ###article-island-ad ###article-sponspred-content ###article-top-728x90-ad-wrapper ###articleAd ###articleAdReplacement ###articleLeftAdColumn ###articleSideAd ###article_LeftAdWords ###article_SponsoredLinks ###article_ad ###article_ad_1 ###article_ad_3 ###article_ad_bottom ###article_ad_bottom_cont ###article_ad_container ###article_ad_rt1 ###article_ad_top ###article_ad_top_cont ###article_ad_w ###article_adholder ###article_ads ###article_advert ###article_banner_ad ###article_bottom_ad01 ###article_box_ad ###article_gallery_desktop_ad ###article_left_ad01 ###article_sidebar_ad ###article_sidebar_ad_02 ###articlead1 ###articlead2 ###articleadblock ###articletop_ad ###articleview_ad ###articleview_ad2 ###artist-ad-container ###aside_ad ###asideads ###asinglead ###atad1 ###atad2 ###atlasAdDivGame ###atwAdFrame0 ###atwAdFrame4 ###autos_banner_ad ###aw-ad-container ###awds-nt1-ad ###awesome-ad ###awp_advertisements-2 ###b-ad-choices ###b-adw ###b5-skyscraper-ad-3 ###b5_ad_footer ###b5_ad_sidebar1 ###b5_ad_top ###b5ad300 ###bLinkAdv ###babAdTop ###backad ###background-adv ###background_ads ###backgroundadvert ###ban_300x250 ###ban_728x90 ###banner-300x250 ###banner-300x250-north ###banner-336x280-north ###banner-336x280-south ###banner-468x60 ###banner-728 ###banner-728adtag ###banner-728adtag-bottom ###banner-728x90 ###banner-ad ###banner-ad-container ###banner-ad-loader ###banner-ads ###banner-advert ###banner-advert-container ###banner-lg-ad ###banner-skyscraper ###banner120x600 ###banner250x250 ###banner300-top-right ###banner300x250 ###banner468 ###banner468x60 ###banner600 ###banner728 ###banner728x90 ###banner975_container ###bannerAd ###bannerAdContainer1_1 ###bannerAdContainer1_2 ###bannerAdContainer1_3 ###bannerAdContainer1_4 ###bannerAdContainer1_5 ###bannerAdContainer1_6 ###bannerAdContainer2_1 ###bannerAdContainer2_2 ###bannerAdContainer2_3 ###bannerAdContainer2_4 ###bannerAdContainer2_5 ###bannerAdContainer2_6 ###bannerAdFrame ###bannerAdLInk ###bannerAdRight3 ###bannerAdTop ###bannerAdWrap ###bannerAdWrapper ###bannerAd_ctr ###bannerAd_rdr ###bannerAds ###bannerGoogle ###banner_280_240 ###banner_300_250 ###banner_300x250_sidebar ###banner_468x60 ###banner_ad ###banner_ad_Sponsored ###banner_ad_bottom ###banner_ad_div_fw ###banner_ad_footer ###banner_ad_module ###banner_ad_placeholder ###banner_admicro ###banner_ads ###banner_adsense ###banner_adv ###banner_advertisement ###banner_adverts ###banner_content_ad ###banner_sedo ###banner_slot ###banner_spacer ###banner_topad ###banner_wrapper_top ###bannerad ###bannerad-bottom ###bannerad-top ###bannerad2 ###banneradrow ###bannerads ###banneradspace ###banneradvert3 ###barAdWrapper ###baseAdvertising ###baseboard-ad ###baseboard-ad-wrapper ###basket-adContainer ###bbContentAds ###bb_ad_container ###bbccom_sponsor_section_text ###bbo_ad1 ###bcaster-ad ###before-footer-ad ###below-listings-ad ###below-post-ad ###belowAd ###belowContactBoxAd ###belowNodeAds ###below_comments_ad_holder ###below_content_ad_container ###belowad ###belowheaderad ###bg-footer-ads ###bg-footer-ads2 ###bg_YieldManager-160x600 ###bg_YieldManager-300x250 ###bg_YieldManager-728x90 ###bg_banner_120x600 ###bg_banner_468x60 ###bg_banner_728x90 ###bgad ###bh_adFrame_ag_300x250_atf ###bh_adFrame_bh_300x250_atf ###bh_adFrame_bh_300x250_btf ###big-box-ad ###bigAd ###bigAd1 ###bigAd2 ###bigAdDiv ###bigBoxAd ###bigBoxAdCont ###big_ad ###big_ad_label ###big_ads ###bigad ###bigad300outer ###bigadbox ###bigadframe ###bigadspace ###bigadspot ###bigboard_ad ###bigboard_ad_ini ###bigbox-ad ###bigsidead ###billboard-ad-container ###billboard_ad ###bl11adv ###blancco-ad ###block--ex_dart-ex_dart_adblade_article ###block-ad_blocks-0 ###block-ad_cube-0 ###block-ad_cube-1 ###block-adsense-0 ###block-adsense-2 ###block-adsense_managed-0 ###block-advert-content ###block-advert-content2 ###block-advertisement ###block-dart-dart-tag-ad_top_728x90 ###block-dart-dart-tag-gfc-ad-top-2 ###block-dctv-ad-banners-wrapper ###block-dfp-skyscraper_left_1 ###block-dfp-skyscraper_left_2 ###block-display-ads-leaderboard ###block-ex_dart-ex_dart_adblade_article ###block-ex_dart-ex_dart_sidebar_ad_block_bottom ###block-ex_dart-ex_dart_sidebar_ad_block_top ###block-fan-ad-fan-ad-front-leaderboard-bottom ###block-fan-ad-fan-ad-front-medrec-top ###block-google-ads ###block-ibtimestv-player-companion-ad ###block-localcom-localcom-ads ###block-openads-0 ###block-openads-1 ###block-openads-13 ###block-openads-14 ###block-openads-2 ###block-openads-3 ###block-openads-4 ###block-openads-5 ###block-openads-brand ###block-openx-0 ###block-openx-1 ###block-openx-4 ###block-openx-5 ###block-sponsors ###block-spti_ga-spti_ga_adwords ###block-thewrap_ads_250x300-0 ###block-thewrap_ads_250x300-1 ###block-thewrap_ads_250x300-2 ###block-thewrap_ads_250x300-3 ###block-thewrap_ads_250x300-4 ###block-thewrap_ads_250x300-5 ###block-thewrap_ads_250x300-6 ###block-thewrap_ads_250x300-7 ###block-views-Advertorial-block_5 ###block-views-Advertorial-block_6 ###block-views-Advertorial-block_7 ###block-views-ad-directory-block ###block-views-premium-ad-slideshow-block ###block-views-sidebar-ad ###block-views-sponsor-block ###blockAd ###blockAds ###block_ad ###block_ad2 ###block_ad_container ###block_advert ###block_advert1 ###block_advert2 ###block_advertisement ###block_timeout_sponsored_0 ###blog-ad ###blog-advert ###blog-header-ad ###blogImgSponsor ###blog_ad_area ###blog_ad_content ###blog_ad_opa ###blog_ad_right ###blog_ad_top ###blogad ###blogad-wrapper ###blogad_728x90_header ###blogad_right_728x91_bottom ###blogad_top_300x250_sidebar ###blogads ###blogads_most_right_ad ###blox-big-ad ###blox-big-ad-bottom ###blox-big-ad-top ###blox-halfpage-ad ###blox-tile-ad ###blox-tower-ad ###bn_ad ###bnr-300x250 ###bnr-468x60 ###bnr-728x90 ###bnrAd ###bnrhd468 ###body-ads ###bodyAd1 ###bodyAd2 ###bodyAd3 ###bodyAd4 ###body_728_ad ###body_ad ###bodymainAd ###bonus-offers-advertisement ###book-ad ###bookmarkListDeckAdPlaceholder ###boss_banner_ad-2 ###boss_banner_ad-3 ###bot_ads ###botad ###botads2 ###bott_ad2 ###bott_ad2_300 ###bottom-728-ad ###bottom-ad ###bottom-ad-1 ###bottom-ad-banner ###bottom-ad-container ###bottom-ad-leaderboard ###bottom-ad-tray ###bottom-ad-wrapper ###bottom-add ###bottom-ads ###bottom-ads-container ###bottom-adspot ###bottom-advertising ###bottom-article-ad-336x280 ###bottom-banner-spc ###bottom-boxad ###bottom-side-ad ###bottom-sponsor-add ###bottomAd ###bottomAd300 ###bottomAdBlcok ###bottomAdCCBucket ###bottomAdContainer ###bottomAdSection ###bottomAdSense ###bottomAdSenseDiv ###bottomAdWrapper ###bottomAds ###bottomAdvBox ###bottomBannerAd ###bottomContentAd ###bottomFullAd ###bottomGoogleAds ###bottomLeftAd ###bottomMPU ###bottomRightAd ###bottomRightAdContainer ###bottomRightAdSpace ###bottomSponsorAd ###bottom_ad ###bottom_ad_area ###bottom_ad_box ###bottom_ad_container ###bottom_ad_left ###bottom_ad_region ###bottom_ad_right ###bottom_ad_unit ###bottom_ad_wrapper ###bottom_adbox ###bottom_ads ###bottom_ads_container ###bottom_advert_container ###bottom_adwrapper ###bottom_banner_ad ###bottom_ex_ad_holder ###bottom_leader_ad ###bottom_overture ###bottom_player_adv ###bottom_sponsor_ads ###bottom_sponsored_links ###bottom_text_ad ###bottomad ###bottomad300 ###bottomad_table ###bottomadbanner ###bottomadbar ###bottomadholder ###bottomads ###bottomadsdiv ###bottomadsense ###bottomadvert ###bottomadwrapper ###bottomleaderboardad ###bottommpuAdvert ###bottommpuSlot ###bottomsponad ###bottomsponsoredresults ###box-ad ###box-ad-section ###box-ad-sidebar ###box-ads-small-1 ###box-ads-small-2 ###box-content-ad ###box-googleadsense-1 ###box-googleadsense-r ###box1ad ###box2ad ###boxAD ###boxAd ###boxAd300 ###boxAdContainer ###boxAdvert ###box_ad ###box_ad_container ###box_ad_middle ###box_ads ###box_advertisement ###box_advertising_info ###box_advertisment ###box_articlead ###box_mod_googleadsense ###box_text_ads ###boxad ###boxad1 ###boxad2 ###boxad3 ###boxad4 ###boxad5 ###boxads ###boxes-box-ad300x250set2 ###boxes-box-ad300x250set2block ###boxes-box-ad_300x250_1 ###boxes-box-ad_728x90_1 ###boxtube-ad ###bpAd ###bps-header-ad-container ###bq_homeMiddleAd ###br_ad ###brand-box-ad ###brand-box-ad-1-container ###branding_click ###browse-ad-container ###browse_ads_ego_container ###browsead ###bsaadvert ###bsap_aplink ###btm_ads ###btmad ###btmsponsoredcontent ###btnAds ###btnads ###btr_horiz_ad ###burn_header_ad ###bus-center-ad ###button-ads ###button-ads-horizontal ###button-ads-vertical ###buttonAdWrapper1 ###buttonAdWrapper2 ###buttonAds ###buttonAdsContainer ###button_ad_container ###button_ad_wrap ###button_ads ###buttonad-widget-3 ###buttonad-widget-4 ###buy-sell-ads ###buySellAds ###buysellads ###buysellads-4x1 ###c-adzone ###c4_ad ###c4ad-Middle1 ###c4ad-Top-parent ###c_ad_sb ###c_ad_sky ###c_sponsoredSquare ###caAdLarger ###carbonads-container ###catad ###catalyst-125-ads ###catalyst-ads-2 ###category-ad ###category-sponsor ###category_sponsorship_ad ###cb-ad ###cb_medrect1_div ###cbs-video-ad-overlay ###cbz-ads-text-link ###cbz-comm-advert-1 ###cellAd ###center-ad ###center-ad-group ###center-ads-72980 ###center-three-ad ###centerAdsHeadlines ###center_ad-0 ###centerads ###central-ads ###cgp-bigbox-ad ###ch-ads ###channel-ads-300-box ###channel-ads-300x600-box ###channel_ad ###channel_ads ###chartAdWrap ###charts_adv ###chatAdv2 ###chatad ###cherry_ads ###ciHomeRHSAdslot ###circ_ad ###circ_ad_300x100 ###circ_ad_620x100 ###circ_ad_holder ###circad_wrapper ###city_House_Ad_300x137 ###clickforad ###cliczone-advert-left ###cliczone-advert-right ###clientAds ###closeAdsDiv ###closeable-ad ###cltAd ###cmMediaRotatorAdTLContainer ###cmn_ad_box ###cmn_ad_tag_head ###cmn_toolbar_ad ###cnhi_premium_ads ###cnnAboveFoldBelowAd ###cnnBottomAd ###cnnCMAd ###cnnRR336ad ###cnnSponsoredPods ###cnnTopAd ###cnnTowerAd ###cnnVPAd ###cnn_cnn_adtag-3 ###coAd ###cobalt-ad-1-container ###coda_ad_728x90_9 ###cokeAd ###col3_advertising ###colAd ###colRightAd ###collapseobj_adsection ###college_special_ad ###column-ads-bg ###column2-145x145-ad ###column4-google-ads ###columnAd ###columnTwoAdContainer ###column_adverts ###column_extras_ad ###commentAdWrapper ###commentTopAd ###comment_ad_zone ###comments-ad-container ###comments-ads ###comments_advert ###commercial-textlinks ###commercial_ads ###commercial_ads_footer ###common_right_ad_wrapper ###common_right_adspace ###common_right_lower_ad_wrapper ###common_right_lower_adspace ###common_right_lower_player_ad_wrapper ###common_right_lower_player_adspace ###common_right_player_ad_wrapper ###common_right_player_adspace ###common_right_right_adspace ###common_top_adspace ###community_ads ###compAdvertisement ###comp_AdsLeaderboardBottom ###comp_AdsLeaderboardTop ###companion-ad ###companionAd ###companionAdDiv ###companion_Ad ###companionad ###componentAdRectangle ###componentAdSkyscraper ###conduitAdPopupWrapper ###container-ad-content-rectangle ###container-ad-topright ###container-polo-ad ###container-righttopads ###container-topleftads ###containerAds980 ###containerLocalAds ###containerLocalAdsInner ###containerMrecAd ###containerSqAd ###container_ad ###container_top_ad ###contener_pginfopop1 ###content-ad ###content-ad-header ###content-ads ###content-advertising-header ###content-advertising-right ###content-columns-post-ad-bottom ###content-columns-post-ad-top ###content-header-ad ###content-left-ad ###content-right-ad ###contentAd ###contentAdSense ###contentAdTwo ###contentAds ###contentAds300x200 ###contentAds300x250 ###contentAds667x100 ###contentAdsCatArchive ###contentBottomAdLeaderboard ###contentBoxad ###contentFooterAD ###contentTopAds2 ###content_0_storyarticlepage_main_0_pnlAdSlot ###content_0_storyarticlepage_main_0_pnlAdSlotInner ###content_0_storyarticlepage_sidebar_0_pnlAdSlot ###content_0_storyarticlepage_sidebar_11_pnlAdSlot ###content_0_storyarticlepage_sidebar_6_pnlAdSlot ###content_11_pnlAdSlot ###content_11_pnlAdSlotInner ###content_16_pnlAdSlot ###content_16_pnlAdSlotInner ###content_2_pnlAdSlot ###content_2_pnlAdSlotInner ###content_3_twocolumnrightfocus_right_bottomright_0_pnlAdSlot ###content_3_twocolumnrightfocus_right_bottomright_1_pnlAdSlot ###content_4_threecolumnallfocus_right_0_pnlAdSlot ###content_7_pnlAdSlot ###content_7_pnlAdSlotInner ###content_9_twocolumnleftfocus_b_right_1_pnlAdSlot ###content_ad ###content_ad_1 ###content_ad_2 ###content_ad_block ###content_ad_container ###content_ad_square ###content_ad_top ###content_ads ###content_ads_content ###content_adv ###content_bottom_ad ###content_bottom_ads ###content_box_300body_sponsoredoffers ###content_box_adright300_google ###content_lower_center_right_ad ###content_mpu ###content_right_ad ###content_right_area_ads ###content_right_side_advertisement_on_top_wrapper ###contentad ###contentad_imtext ###contentad_right ###contentad_urban ###contentadcontainer ###contentads ###contentarea-ad ###contentarea-ad-widget-area ###contentinlineAd ###contents_post_ad ###contest-ads ###contextad ###contextual-ads ###contextual-ads-block ###contextual-ads-bricklet ###contextual-dummy-ad ###contextualad ###corner_ad ###cornerad ###cosponsor ###cosponsorTab ###coverADS ###coverads ###cph_cph_tlda_pnlAd ###crowd-ignite ###crowd-ignite-header ###csBotterAd ###csTopAd ###ct-ad-lb ###ctl00_AdPanel1 ###ctl00_AdPanelISRect2 ###ctl00_AdWords ###ctl00_Adspace_Top_Height ###ctl00_BottomAd ###ctl00_BottomAd2_AdArea ###ctl00_BottomAdPanel ###ctl00_ContentMain_BanManAd468_BanManAd ###ctl00_ContentPlaceHolder1_AdRotator3 ###ctl00_ContentPlaceHolder1_BannerAd_TABLE1 ###ctl00_ContentPlaceHolder1_DrillDown1_trBannerAd ###ctl00_ContentPlaceHolder1_TextAd_Pulse360AdPanel ###ctl00_ContentPlaceHolder1_ad12_adRotator_divAd ###ctl00_ContentPlaceHolder1_blockAdd_divAdvert ###ctl00_ContentPlaceHolder1_ctl00_StoryContainer1_ImageHouseAd ###ctl00_ContentPlaceHolder1_ucAdHomeRightFO_divAdvertisement ###ctl00_ContentPlaceHolder1_ucAdHomeRight_divAdvertisement ###ctl00_ContentPlaceHolder_PageHeading_Special_divGoogleAd2 ###ctl00_ContentRightColumn_RightColumn_Ad1_BanManAd ###ctl00_ContentRightColumn_RightColumn_Ad2_BanManAd ###ctl00_ContentRightColumn_RightColumn_PremiumAd1_ucBanMan_BanManAd ###ctl00_Content_SquareAd_AdBox ###ctl00_Content_skyAd ###ctl00_Footer1_v5footerad ###ctl00_FooterHome1_AdFooter1_AdRotatorFooter ###ctl00_GoogleAd1 ###ctl00_GoogleAd3 ###ctl00_GoogleSkyscraper ###ctl00_Header1_AdHeader1_LabelHeaderScript ###ctl00_HyperLinkHouseAd ###ctl00_ImageHouseAd ###ctl00_LHTowerAd ###ctl00_LeftHandAd ###ctl00_MainContent_adDiv1 ###ctl00_MainContent_adDiv2 ###ctl00_MasterHolder_IBanner_adHolder ###ctl00_SiteHeader1_TopAd1_AdArea ###ctl00_TopAd ###ctl00_TowerAd ###ctl00_VBanner_adHolder ###ctl00__Content__RepeaterReplies_ctl03__AdReply ###ctl00_adCar ###ctl00_adFooter ###ctl00_advert_LargeMPU_div_AdPlaceHolder ###ctl00_advert_WideSky_Right_divOther ###ctl00_bottom_advert_728x90 ###ctl00_cphMainContent_lblPartnerAds ###ctl00_cphMain_adView_dlAds_ctl01_advert_AboveAds_divOther ###ctl00_cphMain_hlAd1 ###ctl00_cphMain_hlAd2 ###ctl00_cphMain_hlAd3 ###ctl00_cphMain_phMain_ctl00_ctl03_ctl00_topAd ###ctl00_cphRoblox_boxAdPanel ###ctl00_ctl00_MainPlaceHolder_itvAdSkyscraper ###ctl00_ctl00_RightColumn1_ctl04_csc300x250Ad1 ###ctl00_ctl00_RightColumn1_ctl04_pnlAdBlock300x250Ad1 ###ctl00_ctl00_RightPanePlaceHolder_pnlAdv ###ctl00_ctl00_ctl00_Main_Main_PlaceHolderGoogleTopBanner_MPTopBannerAd ###ctl00_ctl00_ctl00_Main_Main_SideBar_MPSideAd ###ctl00_ctl00_ctl00_divAdsTop ###ctl00_ctl00_ctl00_tableAdsTop ###ctl00_ctl00_ctl00_tdBannerAd ###ctl00_ctl00_pnlAdBottom ###ctl00_ctl00_pnlAdTop ###ctl00_ctl01_ctl00_tdBannerAd ###ctl00_ctl05_ctl00_tableAdsTop ###ctl00_ctl05_ctl00_tdBannerAd ###ctl00_ctl08_ctl00_tableAdsTop ###ctl00_ctl11_AdvertisementText ###ctl00_ctrlAdvert6_iframeAdvert ###ctl00_ctrlAdvert7_iframeAdvert ###ctl00_ctrlAdvert8_iframeAdvert ###ctl00_divAdSuper ###ctl00_dlTilesAds ###ctl00_fc_ctl02_AdControl ###ctl00_fc_ctl03_AdControl ###ctl00_fc_ctl04_AdControl ###ctl00_fc_ctl06_AdControl ###ctl00_headerAdd ###ctl00_m_skinTracker_m_adLBL ###ctl00_mainContent_lblSponsor ###ctl00_phCrackerMain_ucAffiliateAdvertDisplayMiddle_pnlAffiliateAdvert ###ctl00_phCrackerMain_ucAffiliateAdvertDisplayRight_pnlAffiliateAdvert ###ctl00_pnlAdTop ###ctl00_siteHeader_bannerAd ###ctl00_tc_ctl03_AdControl ###ctl00_tc_ctl04_AdControl ###ctl00_tc_ctl05_AdControl ###ctl00_tc_ctl06_AdControl ###ctl00_tc_ctl14_AdControl ###ctl00_tc_ctl15_AdControl ###ctl00_tc_ctl16_AdControl ###ctl00_tc_ctl18_AdControl ###ctl00_tc_ctl19_AdControl ###ctl00_topAd ###ctl00_ucAffiliateAdvertDisplay_pnlAffiliateAdvert ###ctl00_ucFooter_ucFooterBanner_divAdvertisement ###ctl08_ad1 ###ctl_bottom_ad ###ctl_bottom_ad1 ###ctr-ad ###ctr_adtech2 ###ctr_adtech_mpu_bot ###ctr_adtech_mpu_top ###ctrlsponsored ###ctx_listing_ads ###ctx_listing_ads2 ###cubeAd ###cube_ad ###cube_ads ###cube_ads_inner ###cubead ###cubead-2 ###cubead2 ###currencies-sponsored-by ###custom-advert-leadboard-spacer ###custom-small-ad ###customAd ###cxnAdrail ###d-adCont543x90 ###d-adCont728x90Inner ###d4_ad_google02 ###dAdverts ###dItemBox_ads ###d_AdLink ###dap300x250 ###dart-300x250 ###dart-container-728x90 ###dart_160x600 ###dart_300x250 ###dart_ad_block ###dart_ad_island ###dartad11 ###dartad13 ###dartad16 ###dartad17 ###dartad19 ###dartad25 ###dartad28 ###dartad8 ###dartad9 ###dc-display-right-ad-1 ###dc_ad_data_1 ###dc_ad_data_2 ###dc_ad_data_4 ###dc_advertisement ###dcadSpot-Leader ###dcadSpot-LeaderFooter ###dclinkad ###dcol-sponsored ###dcomad_728x90_0 ###dcomad_ad_728x90_1 ###dcomad_top_300x250_0 ###dcomad_top_300x250_1 ###dcomad_top_300x251_2 ###ddAd ###ddAdZone2 ###defer-adright ###desktop-aside-ad-container ###detail_page_vid_topads ###devil-ad ###dfp-ad-1 ###dfp-ad-2 ###dfp-ad-boombox ###dfp-ad-boombox-wrapper ###dfp-ad-boombox_2 ###dfp-ad-boombox_2-wrapper ###dfp-ad-boombox_3 ###dfp-ad-boombox_3-wrapper ###dfp-ad-boombox_4 ###dfp-ad-boombox_4-wrapper ###dfp-ad-boombox_5 ###dfp-ad-boombox_5-wrapper ###dfp-ad-clone_of_sidebar_top ###dfp-ad-content_1-wrapper ###dfp-ad-content_2-wrapper ###dfp-ad-content_3-wrapper ###dfp-ad-content_4-wrapper ###dfp-ad-fm_300x250-wrapper ###dfp-ad-half_page-wrapper ###dfp-ad-half_page_sidebar-wrapper ###dfp-ad-home_1-wrapper ###dfp-ad-home_2-wrapper ###dfp-ad-home_3-wrapper ###dfp-ad-homepage_300x250-wrapper ###dfp-ad-homepage_728x90 ###dfp-ad-homepage_728x90-wrapper ###dfp-ad-kids_300x250-wrapper ###dfp-ad-large_rectangle ###dfp-ad-large_rectangle-wrapper ###dfp-ad-leaderboard ###dfp-ad-leaderboard-wrapper ###dfp-ad-local_300x250-wrapper ###dfp-ad-medium_rectangle ###dfp-ad-mediumrect-wrapper ###dfp-ad-mediumrectangle-wrapper ###dfp-ad-mediumrectangle2-wrapper ###dfp-ad-mosad_1 ###dfp-ad-mosad_1-wrapper ###dfp-ad-mpu1 ###dfp-ad-mpu2 ###dfp-ad-ne_carousel_300x250 ###dfp-ad-ne_carousel_300x250-wrapper ###dfp-ad-ne_column3a_300x250 ###dfp-ad-ne_column3a_300x250-wrapper ###dfp-ad-ne_news2_468x60 ###dfp-ad-ne_news2_468x60-wrapper ###dfp-ad-pencil_pushdown ###dfp-ad-pencil_pushdown-wrapper ###dfp-ad-right1 ###dfp-ad-right2 ###dfp-ad-right3 ###dfp-ad-schedule_300x250-wrapper ###dfp-ad-slot2 ###dfp-ad-slot3 ###dfp-ad-slot3-wrapper ###dfp-ad-slot4-wrapper ###dfp-ad-slot5 ###dfp-ad-slot5-wrapper ###dfp-ad-slot6 ###dfp-ad-slot6-wrapper ###dfp-ad-slot7 ###dfp-ad-slot7-wrapper ###dfp-ad-stamp_1 ###dfp-ad-stamp_1-wrapper ###dfp-ad-stamp_2 ###dfp-ad-stamp_2-wrapper ###dfp-ad-stamp_3 ###dfp-ad-stamp_3-wrapper ###dfp-ad-stamp_4 ###dfp-ad-stamp_4-wrapper ###dfp-ad-top ###dfp-ad-tower_1 ###dfp-ad-tower_1-wrapper ###dfp-ad-tower_2 ###dfp-ad-tower_2-wrapper ###dfp-ad-tower_half_page ###dfp-ad-tower_half_page-wrapper ###dfp-ad-tv_300x250-wrapper ###dfp-ad-wallpaper ###dfp-ad-wallpaper-wrapper ###dfp-article-mpu ###dfp-article-related-mpu ###dfpAd ###dfp_ad_DictHome_300x250 ###dfp_ad_DictHome_728x90 ###dfp_ad_Entry_160x600 ###dfp_ad_Entry_180x150 ###dfp_ad_Entry_300x250 ###dfp_ad_Entry_728x90 ###dfp_ad_Entry_Btm_300x250 ###dfp_ad_Entry_EntrySetA_300x250 ###dfp_ad_Entry_EntrySetA_728x90 ###dfp_ad_Entry_EntrySetB_300x250 ###dfp_ad_Entry_EntrySetB_728x90 ###dfp_ad_Entry_EntrySetC_728x90 ###dfp_ad_Home_300x250 ###dfp_ad_Home_728x90 ###dfp_ad_Home_Btm_300x250 ###dfp_ad_IC_728x90 ###dfp_ad_InternalAdX_300x250_right ###dfp_ad_Internal_EntryBr_300x250 ###dfp_ad_Internal_Home_250x262 ###dfp_ad_Result_728x90 ###dfp_ad_SecContent_300x250 ###dfp_ad_Thesaurus_728x90 ###dfp_ad_mpu ###dfrads-widget-6 ###dfrads-widget-7 ###dhm-bar ###dict-adv ###direct-ad ###disable-ads-container ###displayAdSet ###displayad_bottom-page ###div-ad-1x1 ###div-ad-1x1_3 ###div-ad-2 ###div-ad-bottom ###div-ad-coupon_1 ###div-ad-coupon_10 ###div-ad-coupon_11 ###div-ad-coupon_12 ###div-ad-coupon_2 ###div-ad-coupon_3 ###div-ad-coupon_4 ###div-ad-coupon_5 ###div-ad-coupon_6 ###div-ad-coupon_7 ###div-ad-coupon_8 ###div-ad-coupon_9 ###div-ad-flex ###div-ad-leaderboard ###div-ad-r ###div-ad-r1 ###div-ad-top ###div-adid-4000 ###div-vip-ad-banner ###divAd ###divAdBox ###divAdHere ###divAdHorizontal ###divAdLeft ###divAdRight ###divAdSpecial ###divAdWrapper ###divAdd728x90 ###divAdd_Right ###divAdd_Top ###divAds ###divAdsTop ###divAdv300x250 ###divAdvertisement ###divAdvertisingSection ###divArticleInnerAd ###divBannerTopAds ###divBottomad1 ###divBottomad2 ###divDoubleAd ###divFoldersAd ###divFooterAd ###divFooterAds ###divLeftAd12 ###divLeftRecAd ###divMenuAds ###divReklamaTop ###divRightNavAdsLoader ###divTopAd ###divTopAds ###divWNAdHeader ###divWNAdUnitLanding ###divWrapper_Ad ###div_ad_TopRight ###div_ad_float ###div_ad_holder ###div_ad_leaderboard ###div_content_mid_lft_ads ###div_googlead ###div_header_sponsors ###div_prerollAd_1 ###div_side_big_ad ###div_video_ads ###divadfloat ###divadsensex ###divmiddlerightad ###divuppercenterad ###divupperrightad ###dlads ###dmRosAdWrapper-MainNorth ###dmRosAdWrapper-east ###dni-advertising-skyscraper-wrapper ###dni-header-ad ###dnn_adSky ###dnn_adTop ###dnn_ad_banner ###dnn_ad_island1 ###dnn_ad_skyscraper ###dnn_ad_sponsored_links ###dnn_banner_120x600 ###dnn_banner_486x60 ###dnn_ctl00_Ad2Pane ###dnn_dnn_dartBanner ###dnn_googleAdsense_a ###dnn_playerAd ###dnn_sponsoredLinks ###docmainad ###dogear_promo ###dotnAd_300x250_c20 ###doubleClickAds3 ###doubleClickAds_bottom_big_box ###doubleClickAds_bottom_skyscraper ###doubleClickAds_top_banner ###doubleclick-island ###download-leaderboard-ad-bottom ###download-leaderboard-ad-top ###downloadAd ###download_ad ###download_ads ###dp_ad_1 ###dp_ads1 ###ds-mpu ###dsStoryAd ###ds_ad_north_leaderboard ###dvAd2Center ###dynamicAdDiv ###dynamicAdWinDiv ###ear_ad ###eastAds ###editorsmpu ###elite-ads ###em_ad_superbanner ###embedAD ###embedded-ad ###embeded_ad_content_container ###entrylist_ad ###eshopad-728x90 ###event_ads ###evotopTen_advert ###ex-ligatus ###ex_dart--ex_dart_header_ad ###exads ###expandableAd ###expandable_welcome_ad ###expanderadblock ###external-links-column-ad ###externalAd ###extra-search-ads ###extraAd ###ezadswidget-2 ###f_ad ###f_adsky ###facebook-ad ###fb_adbox ###fb_rightadpanel ###fearless_responsive_image_ad-2 ###featAds ###featureAd ###featureAdSpace ###feature_ad ###feature_adlinks ###featuread ###featured-ad-left ###featured-ad-right ###featured-ads ###featured-advertisements ###featuredAdContainer2 ###featuredAdWidget ###featuredAds ###featuredSponsors ###featured_ad_links ###featured_sponsor_cnt ###feed_links_ad_container ###feedjiti-footerTR ###ffsponsors ###file_sponsored_link ###fin_ad_728x90_bottom ###fin_advertorial_features ###fin_dc_ad_300x100_pos_1 ###fin_ds_homepage_adtag_468x60 ###first-300-ad ###first-adframe ###first-adlayer ###firstAdUnit ###first_ad ###first_ad_unit ###firstad ###fixedAd ###flAdData6 ###fl_hdrAd ###flash_ads_1 ###flashad ###flex_sponsored_links ###flexiad ###flipbookAd ###floatAD_l ###floatAD_r ###floatads ###floating-ad-spacer ###floating-ads ###floating-advert ###floatingAd ###floatingAds ###floating_ad ###floating_ad_container ###floatyContent ###foot-ad-1 ###foot-add ###footAds ###footad ###footer-ad ###footer-ad-728 ###footer-ad-block ###footer-ad-box ###footer-ad-col ###footer-ad-google ###footer-ad-large ###footer-ad-loader ###footer-ad-shadow ###footer-ad-unit ###footer-ad-wrapper ###footer-ads ###footer-adspace ###footer-adv ###footer-advert ###footer-advert-area ###footer-advertisement ###footer-adverts ###footer-adwrapper ###footer-affl ###footer-banner-ad ###footer-leaderboard-ad ###footer-sponsored ###footerAd ###footerAdBg ###footerAdBottom ###footerAdBox ###footerAdDiv ###footerAdLink ###footerAdd ###footerAds ###footerAdsPlacement ###footerAdvert ###footerAdvertisement ###footerAdverts ###footerGoogleAd ###footer_AdArea ###footer_ad ###footer_ad_01 ###footer_ad_block ###footer_ad_cloud ###footer_ad_container ###footer_ad_holder ###footer_ad_inventory ###footer_ad_modules ###footer_add ###footer_addvertise ###footer_ads ###footer_adsense_ad ###footer_adspace ###footer_adv ###footer_advertising ###footer_leaderboard_ad ###footer_text_ad ###footerad ###footerad728 ###footerads ###footeradsbox ###footeradvert ###form_bottomad ###forum_top_ad ###forumlist-ad ###four_ads ###fp_rh_ad ###fpad1 ###fpad2 ###fpv_companionad ###fr_ad_center ###frameAd ###frameTextAd2 ###frame_admain ###free_ad ###frmRightnavAd ###frnAdSky ###frnBannerAd ###frnContentAd ###front-ad-cont ###front-page-advert ###frontPageAd ###front_ad728 ###front_adtop_content ###front_advert ###front_mpu ###front_mpu_content ###frontlowerad ###frontpage_ad1 ###frontpage_ad2 ###ft-ad ###ft-ad-1 ###ft-ad-container ###ft-ads ###ft_mpu ###full_banner_ad ###fulldown_ads_box ###fulldown_ads_frame ###fullsizebanner_468x60 ###fullstory-google-textad ###fusionad ###fw-advertisement ###fwAdBox ###g-adblock2 ###gAds ###gBnrAd ###gBottomRightAd ###g_ad ###g_adsense ###ga_300x250 ###gad300x250 ###gads300x250 ###gads_middle ###galleries-tower-ad ###gallery-ad ###gallery-ad-m0 ###gallery-advert ###gallery-page-ad-bigbox ###gallery-random-ad ###gallery-slideshow-interstitial-ad ###gallery_ad ###gallery_ads ###gallery_header_ad ###galleryad1 ###game-ad ###game-info-ad ###gameAdMiddle ###gameAdTopMiddle ###gameSquareAd ###game_header_ad ###game_profile_ad_300_250 ###gamead ###gameads ###gamepage_ad ###gameplay_ad ###games-mpu-container ###games_ad_container ###gasense ###gbl_topmost_ad ###gcommonad ###genad ###geoAd ###gft-adChoicesCopy ###gglads ###gglads213A ###gglads213B ###ggogle_AD ###gl_ad_300 ###glamads ###glinkswrapper ###global-banner-ad ###globalHeader_divAd ###globalLeftNavAd ###globalTopNavAd ###global_header_ad ###global_header_ad_area ###gm-ad-lrec ###gmi-ResourcePageAd ###gmi-ResourcePageLowerAd ###gnadww ###go-ads-double-2 ###go-ads-double-3 ###goad1 ###goads ###gog_ad ###gooadtop ###google-ad ###google-ad-art ###google-ad-table-right ###google-ad-tower ###google-ads ###google-ads-bottom ###google-ads-bottom-container ###google-ads-container ###google-ads-container1 ###google-ads-header ###google-ads-left-side ###google-adsense ###google-adsense-for-content ###google-adsense-mpusize ###google-adv-728x90 ###google-adwords ###google-afc ###google-top-ads ###google336x280 ###google468x60 ###googleAd ###googleAdArea ###googleAdBottom ###googleAdBox ###googleAdSenseAdRR ###googleAdTop ###googleAdView ###googleAdYarrp ###googleAd_words ###googleAds ###googleAdsFrame ###googleAdsSml ###googleAdsense ###googleAdsenseAdverts ###googleAdsenseBanner ###googleAdsenseBannerBlog ###googleAdwordsModule ###googleAfcContainer ###googleSearchAds ###googleShoppingAdsRight ###googleShoppingAdsTop ###googleSubAds ###googleTxtAD ###google_ad ###google_ad_468x60_contnr ###google_ad_EIRU_newsblock ###google_ad_below_stry ###google_ad_container ###google_ad_container_right_side_bar ###google_ad_inline ###google_ad_test ###google_ad_top ###google_ads ###google_ads_1 ###google_ads_aCol ###google_ads_box ###google_ads_div_Blog_300 ###google_ads_div_Front-160x600 ###google_ads_div_Raw_Override ###google_ads_div_Second_160 ###google_ads_div_header1 ###google_ads_div_header2 ###google_ads_div_video_wallpaper_ad_container ###google_ads_frame ###google_ads_frame1_anchor ###google_ads_frame2_anchor ###google_ads_frame3_anchor ###google_ads_frame4_anchor ###google_ads_frame5_anchor ###google_ads_frame6_anchor ###google_ads_frame_quad ###google_ads_frame_vert ###google_ads_test ###google_ads_top ###google_ads_wide ###google_adsense ###google_adsense_ad ###google_adsense_home_468x60_1 ###google_textlinks ###googlead ###googlead-leaderboard ###googlead-left ###googlead-post-mpu ###googlead-sidebar-middle ###googlead-sidebar-top ###googlead01 ###googlead2 ###googlead_outside ###googleadbig ###googleadleft ###googleads ###googleads1 ###googleads_h_injection ###googleads_mpu_injection ###googleadsense ###googleadsense300x250 ###googleadsrc ###googleadstop ###googlebanner ###googleblock300 ###googlesponsor ###googletextads ###googtxtad ###gpt-ad-1 ###gpt-ad-halfpage ###gpt-ad-rectangle1 ###gpt-ad-rectangle2 ###gpt-ad-skyscraper ###gpt-ad-story_rectangle3 ###gpt_ad_panorama_top ###gpt_ad_small_insider_1 ###gpt_unit_videoAdSlot1_0 ###gridAdSidebar ###gridAdSidebarRight ###grid_ad ###grouponAdContainer ###gsyadrectangleload ###gsyadrightload ###gsyadtop ###gsyadtopload ###gtAD ###gtopadvts ###gtv_tabSponsor ###gwt-debug-ad ###h-ads ###hAd ###hAdv ###h_ads0 ###h_ads1 ###half-page-ad ###halfPageAd ###halfe-page-ad-box ###hb-header-ad ###hd-ads ###hd-banner-ad ###hd_ad ###hd_ad_wp ###hdr-ad ###hdr-banner-ad ###hdrAdBanner ###hdrAds ###hdtv_ad_ss ###head-ad ###head-ad-1 ###head-ads ###head-advertisement ###head-banner468 ###head1ad ###headAd ###headAds ###headAdv ###headGoogleAffiliateLinkblock ###head_ad ###head_ad_area ###head_ads ###head_advert ###headad ###headadvert ###header-ad ###header-ad-background ###header-ad-block ###header-ad-bottom ###header-ad-container ###header-ad-holder ###header-ad-label ###header-ad-left ###header-ad-rectangle-container ###header-ad-right ###header-ad-wrap ###header-ad2 ###header-ad2010 ###header-ads ###header-adsense ###header-adspace ###header-adv ###header-advert ###header-advert-panel ###header-advertisement ###header-advertising ###header-adverts ###header-advrt ###header-banner-728-90 ###header-banner-ad ###header-banner-spc ###header-block-ads ###header-google ###header-house-ad ###header-lb-ad ###header-leader-ad ###header-leader-ad-2 ###header-top-ads-text ###headerAd ###headerAdBackground ###headerAdButton ###headerAdContainer ###headerAdSpace ###headerAdUnit ###headerAdWrap ###headerAds ###headerAds4 ###headerAdsWrapper ###headerAdv ###headerBannerAdNew ###headerNewAdsContainer ###headerNewAdsContainerB ###headerTopAd ###headerTopAdWide ###header_ad ###header_ad_167 ###header_ad_728 ###header_ad_728_90 ###header_ad_banner ###header_ad_block ###header_ad_container ###header_ad_leaderboard ###header_ad_units ###header_ad_widget ###header_ad_wrap ###header_adbox ###header_adcode ###header_ads ###header_ads2 ###header_ads_2 ###header_ads_p ###header_adsense ###header_adv ###header_advert ###header_advertisement ###header_advertisement_top ###header_advertising ###header_adverts ###header_bottom_ad ###header_flag_ad ###header_leaderboard_ad_container ###header_publicidad ###header_right_ad ###header_sponsors ###header_top_ad ###headerad ###headeradbox ###headeradcontainer ###headerads ###headeradsbox ###headeradsense ###headeradspace ###headeradvert1div ###headeradvertholder ###headeradwrap ###headergooglead ###headerprimaryad ###headersponsors ###headingAd ###headline-sponsor ###headline_ad ###headlinesAdBlock ###hi5-ad-1 ###hidadvnet ###hiddenadAC ###hide_ad_section_v2 ###hideads ###hideads1 ###hl-sponsored-links ###hl-sponsored-results ###hl-top-ad ###hldhdAds ###hly_ad_side_bar_tower_left ###hly_inner_page_google_ad ###hmt-widget-ad-unit-3 ###holder-storyad ###holdunderad ###home-ad ###home-ad-block ###home-ad-slot ###home-adv-300x250 ###home-advert-module ###home-advertise ###home-page-listing-ad ###home-rectangle-ad ###home-right-col-ad ###home-side-ad ###home-top-ads ###homeAd ###homeAdLeft ###homeAds ###homeArticlesAd ###homeBottomAdWrapperInner ###homeMPU ###homePageBotAd ###homeSideAd ###homeTopRightAd ###home_ad ###home_ads_top_hold ###home_ads_vert ###home_bottom_ad ###home_contentad ###home_feature_ad ###home_lower_center_right_ad ###home_mpu ###home_sec2_adverts ###home_sidebar_ad ###home_spensoredlinks ###home_top_right_ad ###homead ###homegoogletextad ###homeheaderad ###homepage-ad ###homepage-adbar ###homepage-footer-ad ###homepage-header-ad ###homepage-right-rail-ad ###homepage-sidebar-ads ###homepageAd ###homepageAdsTop ###homepageFooterAd ###homepageGoogleAds ###homepage_ad ###homepage_rectangle_ad ###homepage_right_ad ###homepage_right_ad_container ###homepage_top_ad ###homepage_top_ads ###homepagead_300x250 ###homepageadvert ###homestream-advert3 ###hometop_234x60ad ###hometopads ###horAd ###hor_ad ###horadslot ###horizad ###horizads728 ###horizontal-ad ###horizontal-adspace ###horizontal-banner-ad ###horizontal-banner-ad-container ###horizontalAd ###horizontal_ad ###horizontal_ad2 ###horizontal_ad_top ###horizontalad ###horizontalads ###hot-deals-ad ###hottopics-advert ###hours_ad ###houseAd ###hp-header-ad ###hp-mpu ###hp-right-ad ###hp-store-ad ###hpSponsor ###hpV2_300x250Ad ###hpV2_googAds ###hp_ad300x250 ###hp_right_ad_300 ###i_ads_table ###iaa_ad ###ibt_local_ad728 ###icePage_SearchLinks_AdRightDiv ###icePage_SearchLinks_DownloadToolbarAdRightDiv ###icePage_SearchResults_ads0_SponsoredLink ###icePage_SearchResults_ads1_SponsoredLink ###icePage_SearchResults_ads2_SponsoredLink ###icePage_SearchResults_ads3_SponsoredLink ###icePage_SearchResults_ads4_SponsoredLink ###icom-ad-top ###idDivAd ###idMapAdvertising ###idRightAdArea ###idSponsoredresultend ###idSponsoredresultstart ###id_SearchAds ###ifmSocAd ###iframe-ad ###iframe-ad-container-Top3 ###iframeAd_2 ###iframeRightAd ###iframeTopAd ###iframe_ad_2 ###iframe_ad_300 ###iframe_ad_728 ###iframe_container300x250 ###iframead-300x250 ###ignad_medrec ###ii_banner_ads ###imPopup ###im_box ###im_popupDiv ###im_popupFixed ###ima_ads-2 ###ima_ads-3 ###ima_ads-4 ###image_selector_ad ###imageadsbox ###imgCollContentAdIFrame ###imgad1 ###imu_ad_module ###in-content-ad ###in-story-ad-wrapper ###in_ad_col_a ###in_post_ad_middle_1 ###in_serp_ad ###inadspace ###inarticlead ###inc-ads-bigbox ###index-ad ###index-bottom-advert ###indexSquareAd ###index_ad ###indexad ###indiv_adsense ###influads_block ###infoBottomAd ###injectableTopAd ###inline-ad ###inline-advert ###inline-story-ad ###inline-story-ad2 ###inlineAd ###inlineAdCont ###inlineAdtop ###inlineAdvertisement ###inlineBottomAd ###inline_ad ###inline_ad_section ###inline_search_ad ###inlinead ###inlineads ###inlinegoogleads ###inlist-ad-block ###inner-ad ###inner-advert-row ###inner-deals-ads ###inner-top-ads ###innerad ###innerpage-ad ###innovativeadspan ###inside-page-ad ###insideCubeAd ###insidearticleBodyAd ###insider_ad_wrapper ###instoryad ###instoryadtext ###instoryadwrap ###insurance-ad-1-container ###int-ad ###intAdUnit ###int_ad ###internalAdvert ###internalads ###interstitialAd ###interstitialAdContainer ###interstitialAdUnit ###interstitial_ad ###interstitial_ad_container ###interstitial_ad_wrapper ###interstitial_ads ###introAds ###invid_ad ###ip-ad-leaderboard ###ip-ad-skyscraper ###ipadv ###iqadcontainer ###iqadoverlay ###iqadtile1 ###iqadtile11 ###iqadtile14 ###iqadtile15 ###iqadtile2 ###iqadtile3 ###iqadtile4 ###iqadtile5 ###iqadtile8 ###iqadtile9 ###iqd_align_Ad ###iqd_mainAd ###iqd_rightAd ###iqd_topAd ###ir-sidebar-ad ###irgoogleadsense ###islandAd ###islandAdPan ###islandAdPane ###islandAdPane2 ###islandAdPaneGoogle ###islandAdSponsored ###island_ad_top ###islandad ###isliveContainer ###item-detail-feature-ad ###itemGroupAd2 ###iwad ###j_ad ###j_special_ad ###ji_medShowAdBox ###jmp-ad-buttons ###jobsAdBox ###joead ###joead2 ###js-ad-leaderboard ###js-image-ad-mpu ###js_adsense ###jt-advert ###jupiter-ads ###ka_adFullBanner ###ka_adMediumRectangle ###ka_adRightSkyscraperWide ###ka_adsense_container ###ka_samplead ###kamidarticle-adnotice ###kamidarticle-middle-content ###karmaAds ###kaufDA-widget ###kdz_ad1 ###kdz_ad2 ###keen_overlay_ad_display ###keyadvertcontainer ###khAdSpace ###ksperAD ###l_home-keen_ad_mask ###landing-adserve ###landing-adserver ###lapho-top-ad-1 ###large-ads ###large-rectange-ad ###large-rectange-ad-2 ###largeAd ###large_rec_ad1 ###largead ###lateAd ###lateralAdWrapper ###launchpad-ads-2 ###layerAds_layerDiv ###layerTLDADSERV ###layer_ad ###layer_ad_content ###layer_ad_main ###layer_adv1 ###layerad ###layeradsense ###lb-ad ###lb-sponsor-left ###lb-sponsor-right ###lbAdBar ###lbAdBarBtm ###lblAds ###lead-ads ###lead_ad ###leadad_1 ###leader-ad ###leader-board-ad ###leaderAd ###leaderAdContainer ###leaderAdContainerOuter ###leaderBoardAd ###leader_ad ###leader_board_ad ###leaderad ###leaderad_section ###leaderadvert ###leaderboard-ad ###leaderboard-ad-1 ###leaderboard-ad-1-container ###leaderboard-ad-1_iframe ###leaderboard-ad-2 ###leaderboard-ad-2_iframe ###leaderboard-ad-3 ###leaderboard-ad-3_iframe ###leaderboard-ad-4 ###leaderboard-ad-4_iframe ###leaderboard-ad-5 ###leaderboard-ad-5_iframe ###leaderboard-ad-bottom ###leaderboard-ad-bottom-container ###leaderboard-ad-container ###leaderboard-advertisement ###leaderboard-bottom-ad ###leaderboardAd ###leaderboardAdArea ###leaderboardAdArea2 ###leaderboardAdLabel ###leaderboardAdSibling ###leaderboardAdTop ###leaderboardAds ###leaderboardAdvert ###leaderboardAdvertFooter ###leaderboardBottomAd ###leaderboard_728x90 ###leaderboard_Ad ###leaderboard_ad ###leaderboard_ad_gam ###leaderboard_ad_main ###leaderboard_ad_unit ###leaderboard_ads ###leaderboard_bottom_ad ###leaderboard_top_ad ###leaderboardad ###leaderboardadtagwidget-2 ###learad ###leatherboardad ###left-ad ###left-ad-1 ###left-ad-2 ###left-ad-col ###left-ad-skin ###left-bottom-ad ###left-col-ads-1 ###left-lower-adverts ###left-lower-adverts-container ###leftAD ###leftAdAboveSideBar ###leftAdCol ###leftAdContainer ###leftAdMessage ###leftAdSpace ###leftAd_fmt ###leftAd_rdr ###leftAds ###leftAdsSmall ###leftAdvert ###leftColumnAdContainer ###leftGoogleAds ###leftSectionAd300-100 ###leftTopAdWrapper ###left_ad ###left_ads ###left_adsense ###left_adspace ###left_adv ###left_advertisement ###left_bg_ad ###left_block_ads ###left_float_ad ###left_side_ads ###left_sidebar_ads ###left_skyscraper_ad ###left_ws_ad_container ###leftad ###leftadg ###leftads ###leftcolAd ###leftcolumnad ###leftframeAD ###lg-banner-ad ###lgfRightBarAd ###lhsBottomAd ###li-right-geobooster-oas ###ligatus ###ligatusdiv ###lilo_imageAd ###linebreak-ads ###linkAdSingle ###linkAds ###link_ads ###linkads ###links-ads-detailnews ###listadholder ###liste_top_ads_wrapper ###listing-ad ###live-ad ###lj_ad_row ###load-adslargerect ###localAds ###logoAd ###logoAd2 ###logo_ad ###long-ad ###long-ad-box ###long-ad-space ###long-bottom-ad-wrapper ###longAdSpace ###longAdWrap ###long_advert_header ###long_advertisement ###lower-advertising ###lowerAdvertisement ###lowerAdvertisementImg ###lower_ad ###lowerads ###lowerthirdad ###lowertop-adverts ###lowertop-adverts-container ###lpAdPanel ###lrec_ad ###lrecad ###lsadvert-left_menu_1 ###lsadvert-left_menu_2 ###lsadvert-top ###mBannerAd ###m_top_adblock ###madison_ad_248_100 ###madskills-ad-manager-0 ###madskills-ad-manager-1 ###madskills-ad-manager-2 ###madskills-ad-manager-3 ###magnify_player_continuous_ad ###main-ad ###main-ad160x600 ###main-ad160x600-img ###main-ad728x90 ###main-advert ###main-advert1 ###main-advert2 ###main-advert3 ###main-bottom-ad ###main-bottom-ad-tray ###main-content-adcontent1 ###main-header-ad-wrap ###main-header-ad-wrap-home ###main-right-ad-tray ###main-tj-ad ###mainAd ###mainAd1 ###mainAdUnit ###mainAdvert ###mainAdvertismentP ###mainHeaderAdvertisment ###mainMenu_divTopAd ###mainPageAds ###mainPlaceHolder_coreContentPlaceHolder_rightColumnAdvert_divControl ###main_AD ###main_ad ###main_ads ###main_content_ad ###main_left_side_ads ###main_rec_ad ###main_top_ad ###main_top_ad_container ###major_ad ###maker-rect-ad ###mapAdvert ###marcoad ###marketing-promo ###marketplace-ad-1 ###marketplace-ad-2 ###marketplaceAds ###marquee_ad ###masSearchAd ###mason_adv_bp_1 ###mason_adv_bp_2 ###mason_adv_bp_3 ###mason_adv_bp_4 ###mason_adv_rn_2 ###mastAd ###mastAdvert ###mast_ad_wrap ###mast_ad_wrap_btm ###mastad ###masterTopAds ###mastercardAd ###masthead-ad ###masthead_ad ###masthead_topad ###matchFooterAd ###mc_ad ###md-sidebar-video-companion-ad-loaded ###md_adLoader ###md_topad ###me-adspace-002 ###med-rect-ad ###medRecAd ###medReqAd ###media-ad ###media-ad-thumbs ###mediaAdLeaderboard ###media_ad ###mediaget_box ###mediagoogleadsense ###mediaplayer_adburner ###medium-ad ###medium-rectangle-ad1 ###mediumAdContainer ###mediumAdvertisement ###mediumRectangleAd ###mediumrectangle_300x250 ###medrec_bottom_ad ###medrec_middle_ad ###medrec_top_ad ###medrectad ###medrectangle_banner ###memberad ###mens-journal-feature-ad ###menu-ads ###menuAds ###menuad ###menubanner-ad-content ###mgid-container ###mhheader_ad ###mi_story_assets_ad ###microAdDiv ###microsoft_ad ###mid-ad300x250 ###mid-table-ad ###midAD ###midRightAds ###midRightTextAds ###mid_ad_div ###mid_ad_title ###mid_left_ads ###mid_mpu ###mid_roll_ad_holder ###midadd ###midadspace ###midadvert ###midbarad ###midbnrad ###midcolumn_ad ###middle-ad ###middle-ad-destin ###middle-story-ad-container ###middleRightColumnAdvert ###middle_ad ###middle_ads ###middle_bannerad ###middle_bannerad_section ###middle_body_advertising ###middle_mpu ###middle_sponsor_ads ###middlead ###middleads ###middleads2 ###midpost_ad ###midrect_ad ###midstrip_ad ###mini-ad ###mini-panel-dart_stamp_ads ###mini-panel-dfp_stamp_ads ###mini-panel-two_column_ads ###miniAdsAd ###mini_ads_inset ###mn_ads ###moa-ads-long ###mobile_ad_spot_header ###mochila-column-right-ad-300x250 ###mochila-column-right-ad-300x250-1 ###mod-partner-center ###mod_ad ###mod_ad_top ###modal-ad ###modal_videoAd_wrapper ###module-ad-300x250 ###module-ad-728x90 ###module-google_ads ###module_ad ###module_box_ad ###module_sky_scraper ###monsterAd ###moogleAd ###more_ad ###moreads ###mos-adCarouselContainer ###mosBannerAd ###mosTileAds ###most_popular_ad ###motionAd ###movads10 ###movieads ###mozo-ad ###mph-rightad ###mpr-ad-leader ###mpr-ad-wrapper-1 ###mpr-ad-wrapper-2 ###mpu-ad ###mpu-advert ###mpu-cont ###mpu-content ###mpu2 ###mpu2_container ###mpu300250 ###mpuAd ###mpuAdvert ###mpuContainer ###mpuDiv ###mpuInContent ###mpuSecondary ###mpuSlot ###mpuWrapper ###mpuWrapper600 ###mpuWrapperAd ###mpuWrapperAd2 ###mpu_300x250 ###mpu_ad ###mpu_ad2 ###mpu_adv ###mpu_banner ###mpu_box ###mpu_container ###mpu_firstpost ###mpu_holder ###mpu_text_ad ###mpuad ###mpubox ###mpuholder ###mpuholder01 ###mpusLeftAd ###mr_banner_topad ###mrec-advertisement ###mrecAdContainer ###mrecPlacement ###msAds ###ms_ad ###msad ###msnAds_inner ###msn_header_ad ###msnau_ad_medium_rectangle ###mtSponsor ###mts_ad_widget ###mu_2_ad ###multiLinkAdContainer ###multi_ad ###multibar-ads ###mvp_160_ad ###my-ads ###my-adsFPAD ###my-adsFPL ###my-adsFPT ###my-adsLREC ###my-adsMAST ###my-medium-rectangle-ad-1-container ###my-medium-rectangle-ad-2-container ###myAd ###myads_HeaderButton ###n_sponsor_ads ###na_adblock ###name-advert ###namecom_ad_hosting_main ###narrow-ad ###narrow_ad_unit ###nat-ad-300x250 ###natadad300x250 ###nationalAd_secondary_btm ###nationalAd_secondary_top ###national_ad ###national_microlink_ads ###nationalad ###nativeadsteaser ###navAdBanner ###nav_ad ###nav_ad_728_mid ###navads-container ###navbar_ads ###navi_banner_ad_780 ###navigation-ad ###nba160PromoAd ###nba300Ad ###nbaGI300ad ###nbaHeaderAds ###nbaHouseAnd600Ad ###nbaLeft600Ad ###nbaMidAds ###nbaVid300Ad ###nbabot728ad ###nbcAd300x250 ###nbcShowcaseAds ###nc-header-ads ###network_header_ad_1 ###new-ad-footer ###new-ad-leaderboard ###new-ad-sidebottom ###new-ad-sidetop ###newAd ###newPostProfileAd ###newPostProfileVerticalAd ###newTopAds ###new_ad_728_90 ###new_ad_header ###new_topad ###newadmpu ###newads ###news_advertorial_content ###news_advertorial_top ###news_article_ad_mrec ###news_article_ad_mrec_right ###news_left_ad ###news_right_ad ###newstream_first_ad ###newuser_ad ###ng_rtcol_ad ###nib-ad ###nlrightsponsorad ###noresults_ad_container ###noresultsads ###northad ###northbanner-advert ###northbanner-advert-container ###notify_ad ###np_content_ads_module ###nrAds ###nrcAd_Top ###ns_ad1 ###ns_ad2 ###ns_ad3 ###ntvads ###nuevo_ad ###oanda_ads ###oas_Middle ###oas_Middle1 ###oas_Right ###oas_Right2 ###oas_Top ###oas_Top1 ###oas_asponsor ###oas_wide_skyscraper ###ob_sponsoredcontent ###oba_message ###objadscript ###oem_ad ###ofie_ad ###omnibar_ad ###onespot-ads ###online_ad ###onpageads ###onpageadstext ###onscroll-ad-holder-mpu2 ###openx-slc ###openx-text-ad ###openx-widget ###openx_iframe ###osDirAd2Post ###osads_300 ###outbrain-paid ###outbrainAdWrapper ###outbrain_dual_ad_fs_0_dual ###outbrain_vertical ###outerAd300 ###outerTwrAd ###outer_div_top_ad ###outsideAds ###ovAd ###ovAdWrap ###ovadsense ###overlay_ad ###overlayadd ###overtureSponsoredLinks ###p-advert ###p-googlead ###p-googleadsense ###p2squaread ###p360_ad_unit ###p_lt_zoneContent_SubContent_p_lt_zoneRight_IFrameAd_panelAd ###page-ad-container-TopLeft ###page-ad-top ###page-advert-3rdrail ###page-advertising ###page-header-ad ###page-top-ad ###pageAdDiv ###pageAdds ###pageAds ###pageAdsDiv ###pageAdvert ###pageBannerAd ###pageOwnershipAd_side ###page_ad ###page_ad_top ###page_content_top_ad ###page_top_ad ###pageads_top ###pagebottomAd ###pagelet_adbox ###pagelet_netego_ads ###pagelet_search_ads2 ###pagelet_side_ads ###pagination-advert ###paidlistingAds ###panel-ad ###panelAd ###panoAdBlock ###parade_300ad ###parade_300ad2 ###partner-ad ###partnerAd ###partnerMedRec ###partnerSitesBannerAd ###partner_ads ###pause-ad ###pauseAd ###pb_report_ad ###pcworldAdBottom ###pcworldAdTop ###pencil-ad ###pencil-ad-container ###perm_ad ###permads ###pf-dialog-ads ###pg-ad-160x600 ###pg-ad-item-160x600 ###pgFooterAd ###pgHeaderAd ###pgSquareAd ###pgad_Bottom3 ###photoAdvert ###photoAndAdBox ###photo_ad_google ###picad_div ###pinball_ad ###pixAd ###plAds ###player-advert ###player-below-advert ###player-midrollAd ###playerAd ###playerAdsRight ###player_ad ###player_ads ###player_middle_ad ###player_top_ad ###playerad ###playvideotopad ###pmad-in1 ###pnAd2 ###pnl_BannerAdServed ###pod-ad-video-page ###pof_ads_Wrapper ###pop_ad ###popadwrap ###popoverAd ###popular-column-ad ###populate_ad_bottom ###populate_ad_left ###populate_ad_textupper ###populate_ad_textupper_textlink ###popupAd ###popupBottomAd ###popup_domination_lightbox_wrapper ###popupadunit ###portlet-advertisement-left ###portlet-advertisement-right ###pos_ContentAd2 ###post-ad ###post-ad-hd ###post-ad-layer ###post-ads ###post-adsense-top-banner ###post-bottom-ads ###post-page-ad ###post-promo-ad ###post5_adbox ###postAd ###postNavigationAd ###post_ad ###post_addsense ###post_adsense ###post_adspace ###post_advert ###post_id_ad_bot ###postpageaddiv ###ppcAdverts ###pr_ad ###pr_advertising ###pre-footer-ad ###pre_advertising_wrapper ###pregame_header_ad ###premSpons ###premier-ad-space ###preminumAD ###premiumAdTop ###premium_ad ###premium_ad_inside ###premiumad ###premiumads ###prerollAd ###preroll_compainion_ad ###priceGrabberAd ###primary_mpu_placeholder ###prime-ad-space ###print-advertisement ###print-header-ad ###print_ads ###printads ###privateadbox ###privateads ###pro_ads_custom_widgets-2 ###pro_ads_custom_widgets-3 ###pro_ads_custom_widgets-5 ###pro_ads_custom_widgets-7 ###pro_ads_custom_widgets-8 ###product-adsense ###profileAdHeader ###proj-bottom-ad ###promo-ad ###promoAds ###promoFloatAd ###promo_ads ###ps-ad-iframe ###ps-top-ads-sponsored ###ps-vertical-ads ###psmpopup ###pub-right-bottom-ads ###pub-right-top-ads ###pub468x60 ###publicGoogleAd ###publicidad ###publicidad-video ###publicidad_120 ###publicidadeLREC ###pulse360_1 ###pushdownAdWrapper ###pushdown_ad ###pusher-ad ###pvadscontainer ###qaSideAd ###qadserve_728x90_StayOn_div ###qm-ad-big-box ###qm-ad-sky ###qm-dvdad ###qpon_big_ad-teaser ###qtopAd-graybg ###quick_ads_frame_bottom ###quidgetad ###quigo ###quigo-ad ###quigo_ad ###quinAdLeaderboard ###r-ad-tag ###r-ads-listings ###r-ads-preview-top ###r1SoftAd ###r_ad3_ad ###r_adver ###rafael_side_ads_widget-5 ###rail-ad-wrap ###rail-bottom-ad ###railAd ###rail_ad ###rail_ad1 ###rail_ad2 ###rbAdWrapperRt ###rbAdWrapperTop ###rc_edu_span5AdDiv ###rd_banner_ad ###reader-ad-container ###realEstateAds ###rearad ###recommendedAdContainer ###rect-ad ###rectAd ###rect_ad ###rectad ###rectangle-ad ###rectangleAd ###rectangleAdSpace ###rectangle_ad ###rectangle_ad_smallgame ###redirect-ad ###redirect-ad-modal ###redirect_ad_1_div ###redirect_ad_2_div ###reference-ad ###refine-300-ad ###refine-ad ###refreshable_ad5 ###region-node-advert ###region-regions-ad-top ###region-top-ad ###reklam-728x90 ###reklama ###reklama_big ###reklama_left_body ###reklama_left_up ###reklama_right_up ###related-ads ###related-projects-sponsor ###related_ad ###related_ads ###related_ads_box ###relatedvideosads2 ###relocation_ad_container ###remove_ads_button1 ###remove_ads_button2 ###removeadlink ###resultSponLinks ###resultsAdsBottom ###resultsAdsSB ###resultsAdsTop ###rg_right_ad ###rh-ad ###rh-ad-container ###rh_tower_ad ###rhapsodyAd ###rhc_ads ###rhsBottomAd ###rhs_ads ###rhs_adverts ###rhsads ###rhsadvert ###richad ###right-ad ###right-ad-1 ###right-ad-block ###right-ad-col ###right-ad-skin ###right-ad-title ###right-ad1 ###right-adds ###right-ads ###right-ads-3 ###right-ads-4 ###right-advert ###right-bar-ad ###right-box-ad ###right-col-ad-600 ###right-featured-ad ###right-mpu-1-ad-container ###right-uppder-adverts ###right-uppder-adverts-container ###right1-ad ###right160x600ads_part ###right2Ad_Iframe ###rightAD ###rightAd ###rightAd1 ###rightAd160x600 ###rightAd160x600two ###rightAd300x250 ###rightAd300x250Lower ###rightAdBar ###rightAdColumn ###rightAdContainer ###rightAdDiv1 ###rightAdDiv2 ###rightAdDiv3 ###rightAdHideLinkContainer ###rightAdHolder ###rightAd_Iframe ###rightAd_rdr ###rightAds ###rightAdsDiv ###rightBottomAd ###rightBoxAdvertisement ###rightBoxAdvertisementLast ###rightColAd ###rightColumnAds ###rightColumnMpuAd ###rightColumnSkyAd ###rightDoubleClick ###rightMortgageAd ###rightSideAd ###right_Ads2 ###right_ad ###right_ad_2 ###right_ad_box ###right_ad_container ###right_ad_top ###right_ad_wrapper ###right_ads ###right_ads_box ###right_adsense ###right_adv1-v2 ###right_advert ###right_advertisement ###right_advertising ###right_adverts ###right_bg_ad ###right_block_ads ###right_column_ad ###right_column_ad_container ###right_column_ads ###right_column_adverts ###right_column_internal_ad_container ###right_column_top_ad_unit ###right_gallery_ad ###right_mini_ad ###right_panel_ads ###right_rail_ad_header ###right_side_bar_ami_ad ###right_sidebar_ads ###right_top_gad ###rightad ###rightad1 ###rightad2 ###rightadBorder ###rightadBorder1 ###rightadBorder2 ###rightadContainer ###rightadd300 ###rightadg ###rightadhome ###rightadpat ###rightads ###rightadsarea ###rightadvertbar-doubleclickads ###rightbar-ad ###rightbar_ad ###rightcol_mgid ###rightcol_sponsorad ###rightcolhouseads ###rightcollongad ###rightcolumn_300x250ad ###rightcolumn_ad_gam ###rightgoogleads ###rightinfoad ###rightrail-ad ###rightrail_ad-0 ###rightside-ads ###rightside_ad ###rightskyad ###righttop-adverts ###righttop-adverts-container ###ringtone-ad-bottom ###ringtone-ad-top ###rm_ad_text ###rockmelt-ad-top ###rolldown-ad ###ros_ad ###rotating-ad-display ###rotating-ads-wrap ###rotating_ad ###rotatingads ###row-ad ###row2AdContainer ###rprightHeaderAd ###rpuAdUnit-0 ###rrAdWrapper ###rr_MSads ###rr_ad ###rr_gallery_ad ###rside_ad ###rside_adbox ###rt-ad ###rt-ad-top ###rt-ad468 ###rtAdvertisement ###rtMod_ad ###rt_side_top_google_ad ###rtcol_advert_1 ###rtcol_advert_2 ###rtm_div_562 ###rtm_html_226 ###rtm_html_920 ###rtmm_right_ad ###rtmod_ad ###rtn_ad_160x600 ###rubicsTextAd ###rxgcontent ###rxgfooter ###rxgheader ###rxgleftbar ###rxgrightbar ###sAdsBox ###s_ads_header ###say-center-contentad ###sb-ad-sq ###sb_ad_links ###sb_advert ###sbads-top ###scoreAD ###scroll-ad ###scroll_banner_ad ###scrollingads ###sct_side_ads ###sdac_bottom_ad_widget-3 ###sdac_footer_ads_widget-3 ###sdac_skyscraper_ad_widget-3 ###sdac_top_ad_widget-3 ###search-ad ###search-ads1 ###search-google-ads ###search-sponsor ###search-sponsored-links ###search-sponsored-links-top ###searchAd ###searchAdFrame ###searchAdSenseBox ###searchAdSenseBoxAd ###searchAdSkyscraperBox ###searchAds ###search_ad ###search_ads ###search_result_ad ###searchresult_advert_right ###searchsponsor ###sec_adspace ###second-adframe ###second-adlayer ###second-right-ad-tray ###second-story-ad ###secondBoxAd ###secondBoxAdContainer ###second_ad_div ###secondad ###secondary_ad_inventory ###secondaryad ###secondrowads ###sect-ad-300x100 ###sect-ad-300x250 ###sect-ad-300x250-2 ###section-ad ###section-ad-1-728 ###section-ad-300-250 ###section-ad-4-160 ###section-ad-bottom ###section-blog-ad ###section-container-ddc_ads ###section-pagetop-ad ###section-sub-ad ###section_ad ###section_advertisements ###section_advertorial_feature ###self-ad ###self_serve_ads ###sensis_island_ad_1 ###sensis_island_ad_1_column ###sensis_island_ad_2 ###sensis_island_ad_2_column ###sensis_island_ad_3 ###sensis_island_ad_3_column ###serveAd1 ###serveAd2 ###serveAd3 ###servfail-ads ###sew-ad1 ###sew_advertbody ###sgAdHeader ###sgAdScGp160x600 ###shellnavAd ###shoppingads ###shortads ###shortnews_advert ###show-ad ###show-player-right-ad ###showAd ###show_ads ###showads ###showcaseAd ###sic_superBannerAd-loader ###sic_superBannerAdTop ###side-ad ###side-ad-container ###side-ads ###side-ads-box ###side-banner-ad ###side-big-ad-bottom ###side-big-ad-middle ###side-boxad ###side-content-ad-1 ###side-content-ad-2 ###side-halfpage-ad ###side-skyscraper-ad ###sideABlock ###sideABlockHeader ###sideAd ###sideAd1 ###sideAd2 ###sideAdArea ###sideAdLarge ###sideAdSmall ###sideAdSub ###sideAds ###sideBannerAd ###sideBar-ads ###sideBarAd ###sideBySideAds ###sideSponsors ###side_ad ###side_ad_call ###side_ad_container_A ###side_ad_module ###side_ad_wrapper ###side_ads ###side_ads_by_google ###side_adv_2 ###side_adverts ###side_longads ###side_sky_ad ###side_skyscraper_ad ###side_sponsors ###sidead ###sidead1 ###sidead1mask ###sideadbox ###sideads ###sideads_container ###sideadscol ###sideadtop-to ###sideadvert ###sideadzone ###sidebar-125x125-ads ###sidebar-125x125-ads-below-index ###sidebar-ad ###sidebar-ad-300 ###sidebar-ad-block ###sidebar-ad-boxes ###sidebar-ad-holdd ###sidebar-ad-holdd-middle ###sidebar-ad-loader ###sidebar-ad-middle ###sidebar-ad-space ###sidebar-ad-wrap ###sidebar-ad1 ###sidebar-ad3 ###sidebar-ad_dbl ###sidebar-ads ###sidebar-ads-content ###sidebar-ads-narrow ###sidebar-ads-wide ###sidebar-ads-wrapper ###sidebar-adspace ###sidebar-adv ###sidebar-advertise-text ###sidebar-advertisement ###sidebar-banner300 ###sidebar-left-ad ###sidebar-long-advertise ###sidebar-main-ad ###sidebar-post-120x120-banner ###sidebar-post-300x250-banner ###sidebar-scroll-ad-container ###sidebar-sponsor-link ###sidebar-sponsors ###sidebar-top-ad ###sidebar-top-ads ###sidebar2-ads ###sidebar2ads ###sidebarAd ###sidebarAd1 ###sidebarAd2 ###sidebarAdSense ###sidebarAdSpace ###sidebarAdUnitWidget ###sidebarAds ###sidebarAdvert ###sidebarSponsors ###sidebarTextAds ###sidebarTowerAds ###sidebar_ad ###sidebar_ad_1 ###sidebar_ad_adam ###sidebar_ad_container ###sidebar_ad_top ###sidebar_ad_widget ###sidebar_ad_wrapper ###sidebar_adblock ###sidebar_ads ###sidebar_ads_180 ###sidebar_box_add ###sidebar_mini_ads ###sidebar_sponsoredresult_body ###sidebar_topad ###sidebar_txt_ad_links ###sidebarad ###sidebarad_300x600-33 ###sidebarad_300x600-4 ###sidebaradpane ###sidebaradsense ###sidebaradver_advertistxt ###sidebaradverts ###sidebard-ads-wrapper ###sidebargooglead ###sidebargoogleads ###sidebarrectad ###sideline-ad ###sidepad-ad ###simple_ads_manager_ad_widget-2 ###simple_ads_manager_widget-3 ###simple_ads_manager_widget-4 ###simplyhired_job_widget ###single-ad ###single-ad-2 ###single-adblade ###single-mpu ###singleAd ###singleAdsContainer ###single_ad_above_content ###singlead ###site-ad-container ###site-ads ###site-leaderboard-ads ###site-sponsors ###siteAdHeader ###site_body_header_banner_ad ###site_bottom_ad_div ###site_content_ad_div ###site_top_ad ###sitead ###sitemap_ad_left ###skcolAdSky ###skin-ad ###skinad-left ###skinad-right ###skinmid-ad ###skinmid-ad_iframe ###sky-ad ###sky-ads ###sky-left ###sky-right ###sky-top-ad ###skyAd ###skyAdContainer ###skyAdNewsletter ###skyScraperAd ###skyScrapperAd ###skyWrapperAds ###sky_ad ###sky_advert ###skyads ###skyadwrap ###skybox-ad ###skyline_ad ###skyscrapeAd ###skyscraper-ad ###skyscraperAd ###skyscraperAdContainer ###skyscraperAdWrap ###skyscraperAds ###skyscraperWrapperAd ###skyscraper_ad ###skyscraper_advert ###skyscraperadblock ###skyscrapper-ad ###slide_ad ###slidead ###slideboxad ###slider-ad ###sliderAdHolder ###slider_ad ###slideshow-middle-ad ###slideshowAd ###slideshow_ad_300x250 ###sm-banner-ad ###smallAd ###smallBannerAdboard ###small_ad ###small_ad_banners_vertical ###small_ads ###smallad ###smallads ###smallerAd ###smxTextAd ###socialAD ###socialBarAd ###socialBarAdMini ###some-ads ###some-ads-holder ###some-more-ads ###source_ad ###source_content_ad ###spec_offer_ad2 ###special-deals-ad ###specialAd_one ###specialAd_two ###special_ads ###specialadfeatures ###specialadvertisingreport_container ###specials_ads ###speed_ads ###speeds_ads ###speeds_ads_fstitem ###speedtest_mrec_ad ###sphereAd ###sphereAd-wrap ###spl_ad ###spnAds ###spnslink ###sponBox ###sponLinkDiv_1 ###sponLinkDiv_2 ###spon_links ###sponlink ###sponlinks ###sponsAds ###sponsLinks ###spons_links ###sponseredlinks ###sponsor-flyout-wrap ###sponsor-links ###sponsorAd ###sponsorAd1 ###sponsorAd2 ###sponsorAdDiv ###sponsorBanners32 ###sponsorBar ###sponsorBorder ###sponsorContainer0 ###sponsorFooter ###sponsorLinkDiv ###sponsorLinks ###sponsorResults ###sponsorSpot ###sponsorTab ###sponsorText ###sponsorTextLink ###sponsor_300x250 ###sponsor_ads ###sponsor_banderole ###sponsor_bar ###sponsor_bottom ###sponsor_box ###sponsor_deals ###sponsor_div ###sponsor_footer ###sponsor_header ###sponsor_link ###sponsor_no ###sponsor_partner_single ###sponsor_posts ###sponsor_right ###sponsored-bucket ###sponsored-features ###sponsored-links ###sponsored-links-container ###sponsored-links-list ###sponsored-links-media-ads ###sponsored-listings ###sponsored-message ###sponsored-not ###sponsored-resources ###sponsored-text-links ###sponsored-widget ###sponsored1 ###sponsoredAdvertisement ###sponsoredBottom ###sponsoredBox1 ###sponsoredBox2 ###sponsoredFeaturedHoz ###sponsoredHoz ###sponsoredLinks ###sponsoredLinksBox ###sponsoredLinks_Bottom ###sponsoredLinks_Top ###sponsoredList ###sponsoredResults ###sponsoredResultsWide ###sponsoredSiteMainline ###sponsoredSiteSidebar ###sponsoredTop ###sponsored_ads ###sponsored_ads_v4 ###sponsored_container ###sponsored_content ###sponsored_game_row_listing ###sponsored_head ###sponsored_label ###sponsored_link ###sponsored_link_bottom ###sponsored_links ###sponsored_native_ad ###sponsored_v12 ###sponsoredads ###sponsoredlinks ###sponsoredlinks_cntr ###sponsoredlinks_left_wrapper ###sponsoredlinkslabel ###sponsoredresultsBottom_body ###sponsoredresults_top ###sponsoredwellcontainerbottom ###sponsoredwellcontainertop ###sponsorlink ###sponsors-block ###sponsors-home ###sponsorsBox ###sponsorsContainer ###sponsors_right_container ###sponsors_top_container ###sponsorsads1 ###sponsorsads2 ###sponsorship-box ###sponsorshipBadge ###sporsored-results ###sports_only_ads ###spotadvert ###spotadvert1 ###spotadvert2 ###spotadvert3 ###spotadvert5 ###spotlight-ad-container-block ###spotlight-ad_iframe ###spotlight-ads ###spotlightAds ###spotlight_ad ###spotlightad ###spr_ad_bg ###spreadly-advertisement-container ###sprint_ad ###sqAd ###sq_ads ###square-ad ###square-ad-box ###square-ad-space ###square-ad-space_btm ###square-ads ###square-sponsors ###squareAd ###squareAdBottom ###squareAdSpace ###squareAdTop ###squareAdWrap ###squareAds ###square_ad ###square_lat_adv ###squaread ###squareadAdvertiseHere ###squared_ad ###srp_adsense-top ###ss-ad-container ###ss-ad-overlay ###st_topads ###starad ###start_middle_container_advertisment ###stationad ###sticky-ad ###sticky-ad-container ###stickyAdBlock ###stickyBottomAd ###stickySkyAd ###stickyads ###stopAdv ###stopAdvt ###story-90-728-area ###story-ad ###story-ad-a ###story-ad-b ###story-ad-top ###story-ad-wrap ###story-leaderboard-ad ###story-page-leaderboard-ad ###story-sponsoredlinks ###storyAd ###storyAdWrap ###story_ad ###story_ads ###story_main_mpu ###story_unseen_ad ###storyad2 ###storyblock-ad ###style_ad_bottom ###subAdsFooter ###subbgad ###subheaderAd ###submenu-ads ###subpage-ad-right ###subpage-ad-top ###subpageAd ###subpage_234x60ad ###sugarad-stitial-overlay ###super_ad ###svp-ad ###swads ###sway-banner-ad ###sway-banner-ad-container ###sway-banner-ad1 ###sweep_right_ad ###sweep_top_ad ###swfAd1 ###swfAd5 ###syn_headerad_zone ###synch-ad ###systemad_background ###t7ad ###tabAdvertising ###table_ads ###taboola-ad ###tailResultAd ###takeover-ad ###takeover_ad ###takeoverad ###targetWeeklyAd ###targetWeeklyAdLogo ###targeted-ads ###tblAd ###tblReklama2 ###tbl_googlead ###tbo_headerads ###tcwAd ###td-GblHdrAds ###td-applet-ads_2_container ###td-applet-ads_container ###tdBannerTopAds ###tdGoogleAds ###td_adunit1 ###td_adunit1_wrapper ###td_adunit2 ###td_sponsorAd ###teaser-adtag-left ###teaser-adtag-right ###temp-ads ###template_ad_leaderboard ###template_affiliates ###tertiary_advertising ###test_adunit_160_article ###text-ad ###text-ads ###text-link-ads ###text-linkAD ###textAd ###textAd1 ###textAds ###textAdsTop ###text_ad ###text_ads ###text_advert ###textad ###textad3 ###textad_block ###textads_right_container ###textlink-advertisement ###textsponsor ###tf_page_ad_content_bottom ###tgAD_imu_2 ###tgAD_imu_3 ###tgAD_imu_4 ###the-last-ad-standing ###theAd ###theadsADT3 ###thefooterad ###thelistBottomAd ###themis-ads ###third_party_ads ###thisisnotanad ###thistad ###thread-ad ###ti-sway-ad ###tile-ad ###tileAds ###tilia_ad ###tippytop-ad ###title-sponsor-banner ###title-wide-sponsored-by ###tmcomp_ad ###tmgAd_div_mpu_1 ###tmglBannerAd ###tmn_ad_1 ###tmn_ad_2 ###tmn_ad_3 ###tmp2_promo_ad ###tnt_ad_column ###toaster_ad ###tobsideAd ###today_ad_bottom ###toolbarSlideUpAd ###top-ad ###top-ad-970x250 ###top-ad-banner ###top-ad-container ###top-ad-content ###top-ad-left-spot ###top-ad-menu ###top-ad-position-inner ###top-ad-rect ###top-ad-right-spot ###top-ad-unit ###top-ad-wrapper ###top-adblock ###top-adds ###top-ads ###top-ads-1 ###top-ads-contain ###top-ads-tabs ###top-adspot ###top-advert ###top-advertisement ###top-advertisements ###top-banner-ad ###top-leaderboard-ad ###top-left-ad ###top-middle-add ###top-right-ad ###top-search-ad-wrapper ###top-sidebar-ad-300x250 ###top-story-ad ###top100_ad300right ###top100_ad300rightbottom ###top2_ads ###top300x250ad ###top3_ads ###top728ad ###topAD ###topAd ###topAd300x250_ ###topAd728x90 ###topAdArea ###topAdBanner ###topAdBar ###topAdBox ###topAdContainer ###topAdDropdown ###topAdHolder ###topAdSenseDiv ###topAdShow ###topAdSpace ###topAdSpace_div ###topAdcontainer ###topAds ###topAds1 ###topAds2 ###topAdsContainer ###topAdsDiv ###topAdsG ###topAdv ###topAdvBox ###topAdvert ###topAdvert-09 ###topBannerAd ###topBannerAdContainer ###topContentAdTeaser ###topImgAd ###topLBAd ###topLeaderAdAreaPageSkin ###topLeaderboardAd ###topMPU ###topMpuContainer ###topNavLeaderboardAdHolder ###topOpenXAdSlot ###topOverallAdArea ###topRightBlockAdSense ###topSponsoredLinks ###top_AD ###top_ad ###top_ad-sense ###top_ad_area ###top_ad_banner ###top_ad_block ###top_ad_box ###top_ad_container ###top_ad_game ###top_ad_inventory ###top_ad_parent ###top_ad_strip ###top_ad_td ###top_ad_unit ###top_ad_wrapper ###top_ad_zone ###top_adblock_fix ###top_add ###top_ads ###top_ads_container ###top_ads_region ###top_ads_wrap ###top_adsense_cont ###top_adspace ###top_adv ###top_adv-v2 ###top_adv_220 ###top_adv_728 ###top_advert ###top_advert_box ###top_advertise ###top_advertising ###top_container_ad ###top_content_ad_inner_container ###top_google_ad_container ###top_google_ads ###top_header_ad_wrapper ###top_mpu ###top_mpu_ad ###top_rectangle_ad ###top_right_ad ###top_span_ad ###top_sponsor_ads ###top_sponsor_text ###top_wide_ad ###topad ###topad-728x90 ###topad1 ###topad2 ###topad728 ###topad_holder ###topad_left ###topad_right ###topad_table ###topadbar ###topadblock ###topadcontainer ###topaddwide ###topadh ###topadone ###topads-spacer ###topads-wrapper ###topadsblock ###topadsdiv ###topadsense ###topadspace ###topadvert ###topadvertisements ###topadvertisementwrapper ###topadwrap ###topadz ###topadzone ###topbanner_ad ###topbanner_sponsor ###topbannerad ###topbanneradtitle ###topbar-ad ###topbarAd ###topbar_Adc1_AdContainer ###topbarads ###topcustomad ###topheader_ads ###topicPageAdsense ###topleaderAd ###topleaderboardad ###topnav-ad-shell ###topnavad ###toppannonse ###topright-ad ###toprightAdvert ###toprightad ###toprow-ad ###topsidebar-ad ###topsponad ###topsponsorads ###topsponsored ###toptextad ###tour300Ad ###tour728Ad ###tourSponsoredLinksContainer ###tower1ad ###towerAdContainer ###towerad ###tr-ad ###tr-adv-banner ###trafficrevenue2 ###transparentad ###travel_ad ###trc_google_ad ###trendex-sponsor-ad ###trib2-footer-ad-back ###trib2-leaderboard-ad-back ###tripleAdInner ###tripleAdOuter ###ts-ad_module ###ttp_ad_slot1 ###ttp_ad_slot2 ###tube_ad ###turnAD ###tut_ads ###twogamesAd ###txfPageMediaAdvertVideo ###txtAdcontainer2 ###txtTextAd ###txt_link_ads ###txtads ###ugly-ad ###ui-about-these-ads-img ###ultraWideAdContainer ###under_content_ad ###under_story_ad ###undergameAd ###universalAdContainer ###uploadMrecAd ###upper-ads ###upperAdvertisementImg ###upperMpu ###upperRightAds ###upper_adbox ###upper_advertising ###upper_small_ad ###upperad ###urban_contentad_1 ###urban_contentad_2 ###urban_contentad_article ###usa_ad_728x90 ###usenetAdsTable ###uvp_ad_container ###uzcrsite ###v_ad ###vap_adsense-top ###variant_adsLazyLoad ###vc_side_ad ###vdiAd ###vdls-adv ###vdls-advs ###vert-ads ###vertAd2 ###vert_ad ###vert_ad_placeholder ###vertad1 ###vertical_ad ###vertical_ads ###vhDivAdSlot300x250 ###vid-left-ad ###vid-right-ad ###vidAdTop ###video-ad-companion-rectangle ###video-adv ###video-coverage-ad-300x250 ###video-embed-ads ###video-header-advert ###video-in-player-ad ###video-in-player-ad-container ###video-under-player-ad ###videoAd ###videoAdvert ###videoCompanionAd ###videoPlayerAdLayer ###video_ads_background ###video_ads_overdiv ###video_adv ###video_advert ###video_advert2 ###video_advert3 ###video_advert_top ###video_cnv_ad ###video_embed_ads ###video_hor_bottom_ads ###video_overlay_ad ###video_vert_right_ads ###videoadlogo ###videoads ###videopageadblock ###view-photo-ad ###viewAd1 ###view_ads_bottom_bg ###view_ads_bottom_bg_middle ###view_ads_content_bg ###view_ads_top_bg ###view_ads_top_bg_middle ###view_adtop ###viewer-ad-bottom ###viewer-ad-top ###viewer_ads_wrapper ###viewportAds ###viewvid_ad300x250 ###visual-ad ###votvAds_inner ###vsw-ads ###vsw_ad ###wTopAd ###wXcds12-ad ###wallAd ###wall_advert ###wallpaper-ad-link ###wallpaperAd_left ###wallpaperAd_left3 ###wallpaperAd_right ###wallpaperAd_right2 ###wallpaperAd_right2_1 ###wallpaper_flash_ad ###wallpaper_header_ad ###walltopad ###watch7-sidebar-ads ###weather-ad ###weather_sponsor ###weatherad ###weblink_ads_container ###websearchAdvert ###welcomeAdsContainer ###welcome_ad ###welcome_ad_mrec ###welcome_advertisement ###wf_ContentAd ###wf_FrontSingleAd ###wf_SingleAd ###wf_bottomContentAd ###wg_ads ###wgtAd ###wh_ad_4 ###whatsnews_footer_ad ###whatsnews_top_ad ###whitepaper-ad ###whoisRightAdContainer ###whoisRightAdContainerBottom ###whoisRightAdContainerTop ###wibiyaAdRotation ###wibiyaToolbarAdUnitFlash ###wideAdd ###wide_ad_unit ###wide_ad_unit2 ###wide_ad_unit_2 ###wide_ad_unit_top ###wide_ad_unit_up ###wide_adv ###wide_right_ad ###wideskyscraper_160x600_left ###wideskyscraper_160x600_right ###widget-ads-3 ###widget-ads-4 ###widget-adv-12 ###widget-box-ad-1 ###widget-box-ad-2 ###widget-style-ad ###widgetADT3 ###widget_Adverts ###widget_ad ###widget_advertisement ###widgetwidget_adserve2 ###wl-pencil-ad ###wog-300x250-ads ###wow-ads ###wp-insert-ad-widget-1 ###wp-topAds ###wp125adwrap_2c ###wp_ad_marker ###wp_pro_ad_system_ad_zone ###wrapAd ###wrapAdRight ###wrapAdTop ###wrapCommentAd ###wrapperAdsTopLeft ###wrapperAdsTopRight ###wrapperRightAds ###wrapper_ad_Top ###wrapper_ad_island2 ###wrapper_sponsoredlinks ###x-ad-item-themed-skyscraper-placekeeper ###x-houseads ###x01-ad ###x300_ad ###xColAds ###xlAd ###xybrad ###y-ad-units ###y708-ad-expedia ###y708-ad-lrec ###y708-ad-partners ###y708-ad-ysm ###y708-advertorial-competitions ###y708-advertorial-marketplace ###yahoo-ads ###yahoo-ads-content ###yahoo-sponsors ###yahooAdsBottom ###yahooSponsored ###yahoo_ad ###yahoo_ad_contanr ###yahoo_ads ###yahoo_sponsor_links ###yahoo_sponsor_links_title ###yahoo_text_ad ###yahooad-tbl ###yahooads ###yan-advert-north ###yan-advert-nt1 ###yan-question-advert ###yan-sponsored ###yatadsky ###ybf-ads ###yfi-sponsor ###yfi_ads_4x4 ###yfi_fp_ad_fx ###yfi_fp_ad_mort ###yfi_fp_ad_nns ###yfi_pf_ad_mort ###ygrp-sponsored-links ###yieldaddiv ###ylf-lrec ###ylf-lrec2 ###ymap_adbanner ###yn-gmy-ad-lrec ###yom-ad-tbs-as ###yrail_ads ###yreSponsoredLinks ###ysm_ad_iframe ###yt-adsfull-widget-2 ###yt-adsfull-widget-3 ###yw-sponsoredad ###zMSplacement1 ###zMSplacement2 ###zMSplacement3 ###zMSplacement4 ###zMSplacement5 ###zMSplacement6 ###zoneAdserverMrec ###zoneAdserverSuper ###zoneAdvertisment ###zone_a_ad ###zone_b_ad ###zone_c_ads ###zztextad ##.AD-POST ##.AD-Rotate ##.AD-label300x250 ##.AD300x600-wrapper ##.AD355125 ##.ADBAR ##.ADBnrArea ##.ADCLOUD ##.ADFooter ##.ADITION ##.ADLeader ##.ADMiddle1 ##.ADPod ##.ADStyle ##.ADTextSingle ##.ADV-Space ##.AD_2 ##.AD_300x100 ##.AD_300x250 ##.AD_300x265 ##.AD_302x252 ##.AD_ALBUM_ITEMLIST ##.AD_MOVIE_ITEM ##.AD_MOVIE_ITEMLIST ##.AD_MOVIE_ITEMROW ##.AD_area ##.AD_mid300 ##.AD_textinfo ##.ADbox ##.ADmid ##.ADouter_div ##.ADwidget ##.Ad-300x100 ##.Ad-Container ##.Ad-Container-976x166 ##.Ad-Header ##.Ad-IframeWrap ##.Ad-MPU ##.Ad-Wrapper-300x100 ##.Ad-label ##.Ad120x600 ##.Ad160x600 ##.Ad160x600left ##.Ad160x600right ##.Ad247x90 ##.Ad300x ##.Ad300x250 ##.Ad300x250L ##.Ad728x90 ##.AdBar ##.AdBody:not(body) ##.AdBorder ##.AdBox ##.AdBox160 ##.AdBox7 ##.AdBox728 ##.AdBoxStyle ##.AdBoxStyleHome ##.AdCaption ##.AdCommercial ##.AdContainer160x600 ##.AdContainerBottom ##.AdContainerBox308 ##.AdContainerModule ##.AdFrameLB ##.AdGraph ##.AdGrayBox ##.AdHeader ##.AdHere ##.AdHolder ##.AdIndicator ##.AdInfo ##.AdInline ##.AdInline_left ##.AdLeftbarBorderStyle ##.AdMedium ##.AdMessage ##.AdModule ##.AdModule_Content ##.AdModule_ContentLarge ##.AdModule_Hdr ##.AdMultiPage ##.AdPanel ##.AdPlaceHolder ##.AdProS728x90Container ##.AdProduct ##.AdRingtone ##.AdScriptBox ##.AdSectionHeader ##.AdSense ##.AdSenseLeft ##.AdSidebar ##.AdSlot ##.AdSlotHeader ##.AdSpace ##.AdTextSmallFont ##.AdTitle ##.AdTop ##.AdUnit ##.AdUnit300 ##.AdUnit300x250 ##.AdUnitBox ##.AdWidget_ImageWidget ##.AdZone120 ##.AdZone316 ##.Ad_120x600 ##.Ad_120x600_holder ##.Ad_160x600_holder ##.Ad_160x600_inner ##.Ad_300x250 ##.Ad_300x250_holder ##.Ad_468x60 ##.Ad_728x90 ##.Ad_728x90_holder ##.Ad_C ##.Ad_D ##.Ad_D_Wrapper ##.Ad_E_Wrapper ##.Ad_Label ##.Ad_Label_foursquare ##.Ad_Right ##.Ad_Tit ##.Ad_container ##.Adbuttons ##.Adbuttons-sidebar ##.AdnetBox ##.Ads-768x90 ##.AdsBottom ##.AdsBottom336X280 ##.AdsBoxBottom ##.AdsBoxSection ##.AdsBoxTop ##.AdsLeft_list ##.AdsLinks1 ##.AdsLinks2 ##.AdsPlayRight_list ##.AdsRec ##.Ads_3 ##.Ads_4 ##.Ads_forum ##.Adsense ##.AdsenseBox ##.AdsenseBoxCenter ##.AdsenseDivFooter ##.AdsenseDownload ##.AdsenseForum ##.AdsenseLarge ##.AdsenseTechsupport ##.Adspottop ##.Adv300x250 ##.Adv468 ##.AdvBoxSidebar ##.Adv_Left ##.Advert300x250 ##.AdvertContainer ##.AdvertMidPage ##.AdvertiseWithUs ##.Advertisehere2 ##.AdvertisementTextTag ##.AdvertisementTop ##.Advertisment ##.AdvertorialTeaser ##.Advman_Widget ##.AffAD ##.AffiliateAds ##.AmazonSimpleAdmin_widget ##.ArticleAd ##.ArticleInlineAd ##.BCA_Advertisement ##.BGoogleAds300 ##.Banner300x250 ##.Banner468X60 ##.BannerAD728 ##.BannerAd ##.Banner_Group ##.Banner_Group_Ad_Label ##.BigBoxAd ##.BigBoxAdLabel ##.BlockAd ##.BlueTxtAdvert ##.BottomAdContainer ##.BottomAffiliate ##.BottomGoogleAds ##.BoxAd ##.BoxAdWrap ##.BoxSponsorBottom ##.BtmAd ##.BtmSponsAd ##.ButtonAd ##.CG_adkit_leaderboard ##.CG_details_ad_dropzone ##.CWReviewsProdInfoAd ##.CollisionAdMarker ##.ComAread ##.CommentAd ##.CommentGoogleAd ##.ContentAd ##.ContentAd2 ##.ContentAds ##.DAWRadvertisement ##.DartAdvert ##.DeptAd ##.DetachedAd ##.DetailAds ##.DisplayAd ##.DomAdsDiv ##.DoubleClickRefreshable ##.EzAdsLUPro ##.EzAdsSearchPro ##.EzAdsWidget ##.FT_Ad ##.FeaturedAdIndexAd ##.FlatAds ##.FooterAdContainer ##.FooterAds ##.FooterTileAdOuter_Div ##.Footer_AD_Links_DIV ##.Footer_Default_AD_Message_DIV ##.GAME_Ad160x600 ##.GOOGLE_AD ##.G_ads ##.G_ads_m ##.GetRightAds ##.GoogleAd ##.GoogleAdInfo ##.GoogleAdSencePanel ##.GoogleAdSenseBottomModule ##.GoogleAdSenseRightModule ##.GoogleAdWords_container ##.GoogleAdsBox ##.GoogleAdsItem ##.GoogleAdv ##.Googleads728 ##.GreenHomeAd ##.GridHouseAdRight ##.HGLoneAdTitleFrame ##.HPG_Ad_B ##.HPNewAdsBannerDiv ##.HPRoundedAd ##.HeaderAd ##.HeaderAds ##.HeaderBannerAd ##.HeaderLeaderAd ##.HeadingAdSpace ##.HomeAd1Label ##.HomeAds ##.HomeContentAd ##.HomeSidebarAd ##.IABAdSpace ##.IM_ad_unit ##.InArticleAd ##.IndexRightAd ##.InternalAdPanel1 ##.JobListMidAd ##.LL_Widget_Advertorial ##.LargeOuterBoxAdsense ##.LargeRightAd ##.LastAd ##.LazyLoadAd ##.LeaderAdvertisement ##.LeaderboardAdTagWidget ##.LeftAd ##.LeftButtonAdSlot ##.LeftTowerAd ##.LeftWideSkyscraperAdPanel ##.Left_Content_Google_Ad ##.Ligatus ##.Loge_AD ##.LoungeAdsBottomLinks ##.M2Advertisement ##.MBoxAdM ##.MBoxAdMain ##.MBoxAdR ##.MBoxAdRight ##.MDCadSummary ##.MD_adZone ##.MOS-ad-hack ##.MPUHolder ##.MPUTitleWrapperClass ##.MPUad ##.MREC_ads ##.MainAdCont ##.Main_right_Adv_incl ##.MarketGid_container ##.MasterLeftContentColumnThreeColumnAdLeft ##.MbanAd ##.MediumRectangleAdPanel ##.MiddleAd ##.MiddleAdContainer ##.MiddleAdvert ##.MspAd ##.NAPmarketAdvert ##.NewsAds ##.OAS_position_TopLeft ##.OSOasAdModule ##.OSProfileAdSenseModule ##.OpaqueAdBanner ##.OpenXad ##.OuterAdvertisingContainer ##.PERFORMANCE_AD_COMPLETE ##.PERFORMANCE_AD_RELATED ##.PU_DoubleClickAdsContent ##.PencilAd ##.Post5ad ##.Post8ad ##.Post9ad ##.PostSidebarAd ##.PremiumObitAdBar ##.ProductAd ##.PushDownAdPane ##.PushdownAd ##.RBboxAd ##.RGAdBoxMainDiv ##.RR_ad ##.RW_ad300 ##.RectangleAd ##.RelatedAds ##.ResponsiveAd ##.Right-Column-AD-Container ##.Right300x250AD ##.RightAd ##.RightAd1 ##.RightAd2 ##.RightAdvertiseArea ##.RightAdvertisement ##.RightGoogleAFC ##.RightGoogleAd ##.RightRailAd ##.RightRailAdbg ##.RightRailAdtext ##.RightRailTop300x250Ad ##.RightSponsoredAdTitle ##.RightTowerAd ##.SRPads ##.STR_AdBlock ##.SecondaryAd ##.SecondaryAdLink ##.SectionSponsor ##.ShootingAd ##.ShootingAdLeft ##.ShowAdDisplay ##.SideAdCol ##.SideAds ##.SidebarAd ##.SidebarAdvert ##.SidebarMiddleAdContainer ##.SidekickItem-Ads ##.SimpleAcceptableTextAds ##.SimpleAcceptebleTextAds ##.SitesGoogleAdsModule ##.Sitewide_AdLabel ##.SkyAdContainer ##.SkyAdContent ##.SkyScraperAd ##.SmartAdZoneList ##.Sponsor-container ##.SponsorAds ##.SponsorIsland ##.SponsorLink ##.SponsoredAdTitle ##.SponsoredArticleAd ##.SponsoredContent ##.SponsoredLinkItemTD ##.SponsoredLinks ##.SponsoredLinksGrayBox ##.SponsoredLinksModule ##.SponsoredLinksPadding ##.SponsoredLinksPanel ##.SponsoredResults ##.Sponsored_link ##.SponsorshipText ##.SquareAd ##.Squareadspot ##.StandardAdLeft ##.StandardAdRight ##.TRADING_AD_RELATED ##.TRU-onsite-ads-leaderboard ##.TTButtAd ##.Tadspacemrec ##.TextAd ##.TextAdds ##.TheEagleGoogleAdSense300x250 ##.ThreeAds ##.TmnAdsense ##.TopAd ##.TopAdContainer ##.TopAdL ##.TopAdR ##.TopAds ##.TopBannerAd ##.TopLeaderboardAdPanel ##.Top_Ad ##.TrafficAd ##.UFSquareAd ##.UIStandardFrame_SidebarAds ##.UIWashFrame_SidebarAds ##.UnderAd ##.UpperAdsContainer ##.VerticalAd ##.Video-Ad ##.VideoAd ##.WPBannerizeWidget ##.WideAdContainer ##.WideAdTile ##.WideAdsLeft ##.WidgetAdvertiser ##.WiredWidgetsDartAds ##.WiredWidgetsGoogleAds ##.WithAds ##.XEad ##.YEN_Ads_120 ##.YEN_Ads_125 ##.ZventsSponsoredLabel ##.ZventsSponsoredList ##.__xX20sponsored20banners ##._bannerAds ##._bottom_ad_wrapper ##._top_ad_wrapper ##.a-d-container ##.a160x600 ##.a300x250 ##.a468x60 ##.a728x90 ##.aa_AdAnnouncement ##.aa_ad-160x600 ##.aa_ad-728x15 ##.aadsection_b1 ##.aadsection_b2 ##.abAdArea ##.abAdPositionBoxB ##.abBoxAd ##.about_adsense ##.aboveCommentAdBladeWrapper ##.aboveCommentAds ##.aboveCommentAdsWrapper ##.above_discussion_ad ##.above_miniscore_ad ##.abovead ##.absoluteAd_wss ##.ac_adbox ##.acm_ad_zones ##.ad--300 ##.ad--468 ##.ad--article-top ##.ad--dart ##.ad--footer ##.ad--google ##.ad--inner ##.ad--large ##.ad--leaderboard ##.ad--mpu ##.ad--top-label ##.ad-1 ##.ad-120-60 ##.ad-120-600-inner ##.ad-120x60 ##.ad-120x600 ##.ad-120x90 ##.ad-125 ##.ad-125x125 ##.ad-140x45-2 ##.ad-150 ##.ad-160 ##.ad-160-160 ##.ad-160-600 ##.ad-160x600 ##.ad-160x600-gallery ##.ad-160x600-home ##.ad-160x600-wrap ##.ad-160x600x1 ##.ad-160x600x2 ##.ad-160x600x3 ##.ad-2 ##.ad-200 ##.ad-200-big ##.ad-200-small ##.ad-200x200 ##.ad-228x94 ##.ad-234 ##.ad-246x90 ##.ad-250 ##.ad-250x125 ##.ad-250x300 ##.ad-260x60 ##.ad-270x100 ##.ad-300 ##.ad-300-250 ##.ad-300-250-600 ##.ad-300-600 ##.ad-300-b ##.ad-300-b-absolute ##.ad-300-block ##.ad-300-blog ##.ad-300-dummy ##.ad-300-flex ##.ad-300x ##.ad-300x100 ##.ad-300x200 ##.ad-300x250 ##.ad-300x250-first ##.ad-300x250-home ##.ad-300x250-right0 ##.ad-300x250-singlepost ##.ad-300x250_600x250 ##.ad-300x600 ##.ad-300x70 ##.ad-300x75 ##.ad-319x128 ##.ad-336x280 ##.ad-336x280B ##.ad-350 ##.ad-355x75 ##.ad-3x1 ##.ad-4 ##.ad-468 ##.ad-468x120 ##.ad-468x60 ##.ad-5 ##.ad-544x250 ##.ad-560 ##.ad-6 ##.ad-600 ##.ad-635x40 ##.ad-7 ##.ad-728 ##.ad-728-90 ##.ad-728x90 ##.ad-728x90-1 ##.ad-728x90-top ##.ad-728x90-top0 ##.ad-728x90_forum ##.ad-768 ##.ad-88-60 ##.ad-88-text ##.ad-90x600 ##.ad-970x50 ##.ad-970x90 ##.ad-BANNER ##.ad-CUSTOM ##.ad-E ##.ad-LREC ##.ad-MPU ##.ad-MediumRectangle ##.ad-RR ##.ad-S ##.ad-SuperBanner ##.ad-W ##.ad-a ##.ad-abc ##.ad-above-header ##.ad-adSense ##.ad-adcode ##.ad-adlink-bottom ##.ad-adlink-side ##.ad-adsense-block-250 ##.ad-alsorectangle ##.ad-area ##.ad-area-small ##.ad-atf ##.ad-atf-medRect ##.ad-b ##.ad-background ##.ad-banner ##.ad-banner-300 ##.ad-banner-bkgd ##.ad-banner-container ##.ad-banner-label ##.ad-banner-leaderboard ##.ad-banner-placeholder ##.ad-banner-smaller ##.ad-banner-top ##.ad-banner-top-wrapper ##.ad-banner728-top ##.ad-banr ##.ad-bar ##.ad-below-player ##.ad-belowarticle ##.ad-bg ##.ad-big ##.ad-big-box ##.ad-bigbox ##.ad-bigboxSub ##.ad-bigsize ##.ad-billboard ##.ad-bline ##.ad-block ##.ad-block-300-widget ##.ad-block-300x250 ##.ad-block-big ##.ad-block-holder ##.ad-block-in-post ##.ad-block-square ##.ad-block-wide ##.ad-blog2biz ##.ad-blogads ##.ad-board ##.ad-body ##.ad-boombox ##.ad-border ##.ad-bordered ##.ad-bot ##.ad-bottom ##.ad-bottom728x90 ##.ad-bottomLeft ##.ad-bottomleader ##.ad-bottomline ##.ad-box-300x250 ##.ad-box-container ##.ad-box-up ##.ad-box1 ##.ad-box2 ##.ad-box3 ##.ad-boxes ##.ad-break ##.ad-breaker ##.ad-breakout ##.ad-browse-rectangle ##.ad-bt ##.ad-btn ##.ad-btn-heading ##.ad-bug-300w ##.ad-button ##.ad-calendar ##.ad-call-300x250 ##.ad-callout ##.ad-caption ##.ad-card-container ##.ad-cat ##.ad-catfish ##.ad-cell ##.ad-center ##.ad-chartbeatwidget ##.ad-choices ##.ad-circ ##.ad-click ##.ad-cluster ##.ad-codes ##.ad-col ##.ad-col-02 ##.ad-column ##.ad-comment ##.ad-companion ##.ad-contain ##.ad-contain-300x250 ##.ad-contain-top ##.ad-container--taboola ##.ad-container-160x600 ##.ad-container-300x250 ##.ad-container-728 ##.ad-container-728x90 ##.ad-container-994x282 ##.ad-container-LEADER ##.ad-container-bot ##.ad-container-dk ##.ad-container-embedded ##.ad-container-leaderboard ##.ad-container-responsive ##.ad-container-right ##.ad-container-side ##.ad-container-tool ##.ad-container-top ##.ad-container-topad ##.ad-container__ad-slot ##.ad-container_row ##.ad-content ##.ad-content-rectangle ##.ad-context ##.ad-d ##.ad-desktop ##.ad-dfp-column ##.ad-dfp-row ##.ad-disclaimer ##.ad-display ##.ad-div ##.ad-diver ##.ad-divider ##.ad-e ##.ad-enabled ##.ad-entry-wrapper ##.ad-exchange ##.ad-expand ##.ad-external ##.ad-f-monster ##.ad-fadein ##.ad-feature-content ##.ad-feature-text ##.ad-feedback ##.ad-field ##.ad-filler ##.ad-fix ##.ad-flag ##.ad-flex ##.ad-footer ##.ad-footer-empty ##.ad-footer-leaderboard ##.ad-forum ##.ad-fullbanner ##.ad-fullbanner-btf-container ##.ad-google ##.ad-google-contextual ##.ad-gpt-breaker ##.ad-gpt-container ##.ad-gpt-main ##.ad-gpt-vertical ##.ad-graphic-large ##.ad-gray ##.ad-grey ##.ad-grid-125 ##.ad-group ##.ad-grp ##.ad-hdr ##.ad-head ##.ad-header ##.ad-header-sidebar ##.ad-heading ##.ad-here ##.ad-hldr-tmc ##.ad-hold ##.ad-holder ##.ad-home-right ##.ad-homeleaderboard ##.ad-homepage ##.ad-homepage-1 ##.ad-homepage-2 ##.ad-hor ##.ad-horizontal-top ##.ad-iab-txt ##.ad-icon ##.ad-identifier ##.ad-iframe ##.ad-imagehold ##.ad-img ##.ad-in-content-300 ##.ad-in-post ##.ad-index ##.ad-index-main ##.ad-indicator-horiz ##.ad-inline ##.ad-inner ##.ad-innr ##.ad-insert ##.ad-inserter ##.ad-internal ##.ad-interruptor ##.ad-island ##.ad-item ##.ad-item-related ##.ad-label ##.ad-lable ##.ad-landscape ##.ad-large-game ##.ad-layer ##.ad-lazy-support-yes ##.ad-lb ##.ad-lead ##.ad-lead-bottom ##.ad-leader ##.ad-leader-bottom ##.ad-leader-plus-top ##.ad-leader-top ##.ad-leader-wrap ##.ad-leaderboard ##.ad-leaderboard-companion ##.ad-leaderboard-container ##.ad-leaderboard-marquee ##.ad-leaderboard_river ##.ad-leadtop ##.ad-left ##.ad-left3 ##.ad-leftrail ##.ad-line ##.ad-link ##.ad-link-left ##.ad-link-right ##.ad-links ##.ad-loaded ##.ad-location ##.ad-location-header ##.ad-lower_rec ##.ad-lower_river ##.ad-lrec ##.ad-manager-ad ##.ad-marker ##.ad-marketplace ##.ad-marketplace-horizontal ##.ad-marketswidget ##.ad-med ##.ad-med-rec ##.ad-med-rect ##.ad-med-rect-tmp ##.ad-medRec ##.ad-medium ##.ad-medium-rectangle ##.ad-medium-two ##.ad-medrect ##.ad-megaboard ##.ad-message ##.ad-messaging ##.ad-midleader ##.ad-mobile ##.ad-mobile-banner ##.ad-mod ##.ad-module ##.ad-mpl ##.ad-mpu ##.ad-mpu-bottom ##.ad-mpu-middle ##.ad-mpu-middle2 ##.ad-mpu-placeholder ##.ad-mpu-plus-top ##.ad-mpu-top ##.ad-mrec ##.ad-mrect ##.ad-msg ##.ad-msgunit ##.ad-msn ##.ad-national-1 ##.ad-new ##.ad-no-style ##.ad-noBorderAndMargin ##.ad-noline ##.ad-note ##.ad-notice ##.ad-on ##.ad-one ##.ad-other ##.ad-outlet ##.ad-outside ##.ad-packs ##.ad-padding ##.ad-page-leader ##.ad-page-medium ##.ad-pagehead ##.ad-panel ##.ad-panorama ##.ad-parallax-wrap ##.ad-parent-hockey ##.ad-passback-o-rama ##.ad-pb ##.ad-peg ##.ad-permalink ##.ad-personalise ##.ad-place-active ##.ad-place-holder ##.ad-placeholder ##.ad-placement ##.ad-plea ##.ad-position ##.ad-position-1 ##.ad-post ##.ad-postText ##.ad-poster ##.ad-primary ##.ad-primary-sidebar ##.ad-priority ##.ad-pro70 ##.ad-promo ##.ad-promoted-game ##.ad-pushdown ##.ad-r ##.ad-rail ##.ad-rect ##.ad-rect-atf-01 ##.ad-rect-top-right ##.ad-rectangle ##.ad-rectangle-banner ##.ad-rectangle-long ##.ad-rectangle-long-sky ##.ad-rectangle-text ##.ad-rectangle-wide ##.ad-rectangle-xs ##.ad-region-delay-load ##.ad-related ##.ad-relatedbottom ##.ad-responsive-wide ##.ad-rh ##.ad-ri ##.ad-right ##.ad-right-header ##.ad-right-txt ##.ad-right1 ##.ad-right2 ##.ad-right3 ##.ad-rotation ##.ad-row ##.ad-row-viewport ##.ad-s ##.ad-s-rendered ##.ad-scl ##.ad-script-processed ##.ad-section ##.ad-section-body ##.ad-sense ##.ad-sep ##.ad-served ##.ad-shifted ##.ad-show-label ##.ad-showcase ##.ad-side ##.ad-side-one ##.ad-sidebar ##.ad-sidebar-180-150 ##.ad-sidebar-300-250 ##.ad-sidebar-ad-message ##.ad-sidebar-border ##.ad-sidebar-outer ##.ad-sidebar300 ##.ad-siderail ##.ad-signup ##.ad-sitewide ##.ad-sky ##.ad-skyscr ##.ad-skyscraper ##.ad-skyscraper-label ##.ad-slider ##.ad-slot ##.ad-slot--inline ##.ad-slot--mpu-banner-ad ##.ad-slot-1 ##.ad-slot-2 ##.ad-slot-234-60 ##.ad-slot-300-250 ##.ad-slot-728-90 ##.ad-slot-a ##.ad-slot-container ##.ad-slot-sidebar ##.ad-slot-sidebar-b ##.ad-slot__label ##.ad-slot__oas ##.ad-smallBP ##.ad-source ##.ad-sp ##.ad-space ##.ad-space-mpu-box ##.ad-space-topbanner ##.ad-spacer ##.ad-speedbump ##.ad-sponsor ##.ad-sponsor-large-container ##.ad-sponsor-text ##.ad-sponsored-links ##.ad-sponsored-post ##.ad-sponsors ##.ad-spot ##.ad-spotlight ##.ad-square ##.ad-square2-container ##.ad-square300 ##.ad-squares ##.ad-stack ##.ad-statement ##.ad-sticky ##.ad-story-inject ##.ad-story-top ##.ad-strip ##.ad-subtitle ##.ad-t ##.ad-table ##.ad-tabs ##.ad-tag ##.ad-tag-square ##.ad-tall ##.ad-target2-wrapper ##.ad-text ##.ad-text-blockA01 ##.ad-text-blockB01 ##.ad-text-label ##.ad-text-link ##.ad-text-links ##.ad-textG01 ##.ad-textads ##.ad-thanks ##.ad-tile ##.ad-tl1 ##.ad-top ##.ad-top-300x250 ##.ad-top-728 ##.ad-top-728x90 ##.ad-top-box-right ##.ad-top-in ##.ad-top-lboard ##.ad-top-left ##.ad-top-rectangle ##.ad-top-wrapper ##.ad-top1 ##.ad-top2 ##.ad-topleader ##.ad-topright ##.ad-tower ##.ad-txt ##.ad-type1 ##.ad-type10 ##.ad-type2 ##.ad-type3 ##.ad-unit ##.ad-unit-300 ##.ad-unit-300-wrapper ##.ad-unit-anchor ##.ad-unit-container ##.ad-unit-inline-center ##.ad-unit-medium-retangle ##.ad-unit-mpu ##.ad-unit-top ##.ad-update ##.ad-upper_rec ##.ad-us ##.ad-vert ##.ad-vertical ##.ad-vertical-container ##.ad-vertical-stack-ad ##.ad-vtu ##.ad-w300 ##.ad-wallpaper-panorama-container ##.ad-warning ##.ad-wgt ##.ad-wide ##.ad-widget ##.ad-widget-area ##.ad-widget-list ##.ad-windowshade-full ##.ad-wings__link ##.ad-with-background ##.ad-with-us ##.ad-wrap ##.ad-wrapper ##.ad-x10x20x30 ##.ad-x31-full ##.ad-zone ##.ad-zone-s-q-l ##.ad.super ##.ad01 ##.ad02 ##.ad03 ##.ad04 ##.ad08sky ##.ad1-left ##.ad1-right ##.ad10 ##.ad100 ##.ad1000 ##.ad1001 ##.ad100x100 ##.ad120 ##.ad120_600 ##.ad120x120 ##.ad120x240GrayBorder ##.ad120x240backgroundGray ##.ad120x60 ##.ad120x600 ##.ad125 ##.ad125x125 ##.ad125x125a ##.ad125x125b ##.ad140 ##.ad160 ##.ad160600 ##.ad160_blk ##.ad160_l ##.ad160_r ##.ad160x160 ##.ad160x600 ##.ad160x600GrayBorder ##.ad160x600box ##.ad170x30 ##.ad18 ##.ad180 ##.ad185x100 ##.ad19 ##.ad1Image ##.ad1_bottom ##.ad1_latest ##.ad1_top ##.ad1b ##.ad1left ##.ad1x1 ##.ad200 ##.ad200x60 ##.ad220x50 ##.ad230 ##.ad233x224 ##.ad234 ##.ad234x60 ##.ad236x62 ##.ad240 ##.ad250 ##.ad250-h1 ##.ad250-h2 ##.ad250c ##.ad250wrap ##.ad250x250 ##.ad260x60 ##.ad284x134 ##.ad2content_box ##.ad300 ##.ad300-hp-top ##.ad3001 ##.ad300250 ##.ad300Block ##.ad300Wrapper ##.ad300_2 ##.ad300_250 ##.ad300_bg ##.ad300_ver2 ##.ad300b ##.ad300banner ##.ad300mrec1 ##.ad300shows ##.ad300top ##.ad300w ##.ad300x-placeholder ##.ad300x100 ##.ad300x111 ##.ad300x120 ##.ad300x150 ##.ad300x250 ##.ad300x250-1 ##.ad300x250-2 ##.ad300x250-home ##.ad300x250-hp-features ##.ad300x250-inline ##.ad300x250-stacked ##.ad300x2501 ##.ad300x250GrayBorder ##.ad300x250Module ##.ad300x250Right ##.ad300x250Top ##.ad300x250_box ##.ad300x250_container ##.ad300x250a ##.ad300x250b ##.ad300x250box ##.ad300x250box2 ##.ad300x250flex ##.ad300x250s ##.ad300x40 ##.ad300x50-right ##.ad300x600 ##.ad300x77 ##.ad300x90 ##.ad310 ##.ad315 ##.ad320x250 ##.ad336 ##.ad336x280 ##.ad336x362 ##.ad343x290 ##.ad350 ##.ad360 ##.ad400right ##.ad400x40 ##.ad450 ##.ad468 ##.ad468_60 ##.ad468x60 ##.ad468x60Wrap ##.ad468x60_main ##.ad470x60 ##.ad530 ##.ad540x90 ##.ad590 ##.ad590x90 ##.ad5_container ##.ad600 ##.ad612x80 ##.ad620x70 ##.ad626X35 ##.ad640x480 ##.ad640x60 ##.ad644 ##.ad650x140 ##.ad652 ##.ad670x83 ##.ad728 ##.ad72890 ##.ad728By90 ##.ad728_90 ##.ad728_blk ##.ad728_cont ##.ad728_wrap ##.ad728cont ##.ad728h ##.ad728x90 ##.ad728x90-1 ##.ad728x90-2 ##.ad728x90WithLabel ##.ad728x90_2 ##.ad728x90_container ##.ad728x90box ##.ad728x90btf ##.ad728x90container ##.ad768x90 ##.ad90 ##.ad90x780 ##.ad940x30 ##.ad954x60 ##.ad960 ##.ad960x185 ##.ad960x90 ##.ad970x30 ##.ad970x90 ##.ad980 ##.ad980x120 ##.ad980x50box ##.ad987 ##.adAgate ##.adAlert ##.adAlone300 ##.adArea ##.adArea674x60 ##.adAreaLC ##.adArticleBanner ##.adArticleBody ##.adArticleRecommend ##.adArticleSidetile ##.adArticleTopText ##.adAuto ##.adBGcolor ##.adBan ##.adBanner ##.adBanner300x250 ##.adBanner728x90 ##.adBannerTyp1 ##.adBannerTypSortableList ##.adBannerTypW300 ##.adBar ##.adBarCenter ##.adBarLeft ##.adBarRight ##.adBelt ##.adBgBottom ##.adBgClick ##.adBgMId ##.adBgTop ##.adBigBoxFirst ##.adBillboard ##.adBkgd ##.adBlock ##.adBlock-300-250 ##.adBlock160x600Spot1 ##.adBlockBottom ##.adBlockBottomBreak ##.adBlockNext ##.adBlockSpacer ##.adBlockSpot ##.adBlock_1 ##.adBlock_14 ##.adBlock_15 ##.adBlock_17 ##.adBlock_2 ##.adBlock_3 ##.adBlock_6 ##.adBlock_8 ##.adBlock_9 ##.adBodyBlockBottom ##.adBorder ##.adBorders ##.adBottomBoard ##.adBottomLink ##.adBottomboxright ##.adBox ##.adBox-mr ##.adBox1 ##.adBox2 ##.adBox230X96 ##.adBox250 ##.adBox3b ##.adBox5 ##.adBox6 ##.adBox728 ##.adBox728X90 ##.adBox728X90_header ##.adBoxBody ##.adBoxBorder ##.adBoxContainer ##.adBoxContent ##.adBoxFooter ##.adBoxHeader ##.adBoxInBignews ##.adBoxSidebar ##.adBoxSingle ##.adBoxTitle ##.adBox_1 ##.adBox_3 ##.adBrandpanel ##.adBtm ##.adBuyRight ##.adBwrap ##.adCMRight ##.adCMSlide ##.adCall ##.adCell ##.adCenter ##.adCenterAd ##.adCentered ##.adCentertile ##.adChoice ##.adChoiceLogo ##.adChoicesLogo ##.adClm ##.adClose ##.adCode ##.adColBgBottom ##.adColumn ##.adColumnLeft ##.adComponent ##.adCont ##.adContRight ##.adContTop ##.adContainer1 ##.adContainerRectangle ##.adContainer_125x125 ##.adContainer_728x90 ##.adContainerg6 ##.adContent ##.adContentAd ##.adContour ##.adCreative ##.adCs ##.adCube ##.adDialog ##.adDingT ##.adDiv ##.adDivSmall ##.adElement ##.adEmployment ##.adFender3 ##.adFooterLinks ##.adFrame ##.adFrameCnt ##.adFrameContainer ##.adFrames ##.adFtr ##.adFull ##.adFullWidth ##.adFullWidthBottom ##.adFullWidthMiddle ##.adGlobalHeader ##.adGogleBox ##.adGoogle ##.adGroup ##.adHead ##.adHeader ##.adHeaderAdbanner ##.adHeaderText ##.adHeaderblack ##.adHeadline ##.adHeadlineSummary ##.adHed ##.adHolder ##.adHolder2 ##.adHoldert ##.adHome300x250 ##.adHorisontal ##.adHorisontalNoBorder ##.adHorizontalTextAlt ##.adHplaceholder ##.adIMm ##.adIframeCount ##.adImg ##.adImgIM ##.adInArticle ##.adInNews ##.adInner ##.adInnerLeftBottom ##.adInteractive ##.adIsland ##.adItem ##.adLabel ##.adLabel160x600 ##.adLabel300x250 ##.adLabelLine ##.adLabels ##.adLargeRec ##.adLargeRect ##.adLeader ##.adLeaderForum ##.adLeaderboard ##.adLeft ##.adLink ##.adLinkCnt ##.adListB ##.adLoaded ##.adLoader ##.adLocal ##.adLocation ##.adMPU ##.adMPUHome ##.adMarker ##.adMarkerBlock ##.adMastheadLeft ##.adMastheadRight ##.adMedRectBox ##.adMedRectBoxLeft ##.adMediaMiddle ##.adMediumRectangle ##.adMegaBoard ##.adMeldGuts ##.adMessage ##.adMiddle ##.adMiniTower ##.adMinisLR ##.adMkt2Colw ##.adMod ##.adModule ##.adModule300 ##.adModuleAd ##.adModule_square2 ##.adMpu ##.adMpuHolder ##.adNetPromo ##.adNewsChannel ##.adNoBorder ##.adNoOutline ##.adNone ##.adNote ##.adNotice ##.adNotice90 ##.adNoticeOut ##.adNotification ##.adObj ##.adOne ##.adOuterContainer ##.adOverlay ##.adPageBorderL ##.adPageBorderR ##.adPanel ##.adPanelContent ##.adPlaceholder ##.adPlaceholder35 ##.adPlaceholder54 ##.adPlaceholder_foot ##.adPod ##.adPosition ##.adRecommend ##.adRecommendRight ##.adRect ##.adRectangle ##.adRectangleUnit ##.adRegionSelector ##.adRemove ##.adReportsLink ##.adResult ##.adResults ##.adRight ##.adRotator ##.adRow ##.adSKY ##.adSTHomePage ##.adSection ##.adSection_rt ##.adSelfServiceAdvertiseLink ##.adSenceImagePush ##.adSense ##.adSepDiv ##.adServer ##.adSeven ##.adSide ##.adSide203 ##.adSide230 ##.adSidebarButtons ##.adSidetileplus ##.adSize_MedRec ##.adSky ##.adSky600 ##.adSkyOrMpu ##.adSkyscaper ##.adSkyscraper ##.adSkyscraperHolder ##.adSlice ##.adSlide ##.adSlot ##.adSlotContainer ##.adSlug ##.adSpBelow ##.adSpace ##.adSpace300x250 ##.adSpace950x90 ##.adSpacer ##.adSplash ##.adSponsor ##.adSponsorText ##.adSpot ##.adSpot-brought ##.adSpot-mrec ##.adSpot-searchAd ##.adSpot-textBox ##.adSpot-textBoxGraphicRight ##.adSpot-twin ##.adSpotIsland ##.adSquare ##.adStatementText ##.adStyle1 ##.adSubColPod ##.adSummary ##.adSuperboard ##.adSupertower ##.adTD ##.adTXTnew ##.adTab ##.adTag ##.adTag-wrap ##.adText ##.adTextPmpt ##.adTicker ##.adTileWrap ##.adTiler ##.adTitle ##.adTitleR ##.adTopBanner_nomobile ##.adTopBk ##.adTopHome ##.adTopLeft ##.adTopLink ##.adTopRight ##.adTopboxright ##.adTout ##.adTower ##.adTwo ##.adTxt ##.adType2 ##.adUnit ##.adUnitHorz ##.adUnitVert ##.adUnitVert_noImage ##.adVar ##.adVertical ##.adVideo ##.adVplaceholder ##.adWarning ##.adWebBoard ##.adWideSkyscraper ##.adWideSkyscraperRight ##.adWidget ##.adWidgetBlock ##.adWithTab ##.adWord ##.adWrap ##.adWrapLg ##.adZone ##.adZoneRight ##.ad_0 ##.ad_1 ##.ad_1000x90 ##.ad_100x100 ##.ad_120x60 ##.ad_120x600 ##.ad_120x90 ##.ad_125 ##.ad_130x90 ##.ad_150x150 ##.ad_160 ##.ad_160_600 ##.ad_160x600 ##.ad_180x150 ##.ad_1day9 ##.ad_2 ##.ad_200 ##.ad_200x200 ##.ad_234x60 ##.ad_240 ##.ad_240x400 ##.ad_242_90_top ##.ad_250 ##.ad_250x200 ##.ad_250x250 ##.ad_250x250_w ##.ad_3 ##.ad_300 ##.ad_300250 ##.ad_300Home ##.ad_300Side ##.ad_300_120 ##.ad_300_250 ##.ad_300_250_1 ##.ad_300_250_2 ##.ad_300_250_cpv ##.ad_300_250_wrapper ##.ad_300_600 ##.ad_300s ##.ad_300x100 ##.ad_300x240 ##.ad_300x250 ##.ad_300x250_box_right ##.ad_300x250_live ##.ad_300x50 ##.ad_300x500 ##.ad_300x60 ##.ad_300x600 ##.ad_320x250_async ##.ad_320x360 ##.ad_326x260 ##.ad_330x110 ##.ad_336 ##.ad_336_gr_white ##.ad_336x280 ##.ad_336x90 ##.ad_338_282 ##.ad_350x100 ##.ad_350x250 ##.ad_4 ##.ad_400x200 ##.ad_468 ##.ad_468x60 ##.ad_4_row ##.ad_5 ##.ad_600 ##.ad_630x130 ##.ad_640x90 ##.ad_680x15 ##.ad_728 ##.ad_72890 ##.ad_72890_box ##.ad_728Home ##.ad_728_90 ##.ad_728_90_1 ##.ad_728_90_top ##.ad_728_90b ##.ad_728_in ##.ad_728_top ##.ad_728_v2 ##.ad_728x90 ##.ad_728x90-1 ##.ad_728x90-2 ##.ad_728x90_top ##.ad_728x90b ##.ad_88x31 ##.ad_925x90 ##.ad_954-60 ##.ad_960 ##.ad_970x90_prog ##.ad_980x260 ##.ad_CustomAd ##.ad_Flex ##.ad_Left ##.ad_Right ##.ad__label ##.ad__rectangle ##.ad__wrapper ##.ad_a ##.ad_adInfo ##.ad_ad_160 ##.ad_ad_300 ##.ad_adblade ##.ad_adsense_spacer ##.ad_adv ##.ad_amazon ##.ad_area_two ##.ad_article_top_left ##.ad_atf_300x250 ##.ad_atf_728x90 ##.ad_avu_300x250 ##.ad_back ##.ad_background ##.ad_bank_wrapper ##.ad_banner ##.ad_banner2 ##.ad_banner_2 ##.ad_banner_234 ##.ad_banner_468 ##.ad_banner_728x90_inner ##.ad_banner_border ##.ad_banner_div ##.ad_bar ##.ad_below_content ##.ad_belowmenu ##.ad_bg ##.ad_bg_300x250 ##.ad_big_banner ##.ad_bigbox ##.ad_billboard ##.ad_biz ##.ad_blk ##.ad_block ##.ad_block_1 ##.ad_block_2 ##.ad_block_300x250 ##.ad_block_336 ##.ad_block_338 ##.ad_block__336_d1 ##.ad_block_leader2 ##.ad_body ##.ad_border ##.ad_botbanner ##.ad_bottom ##.ad_bottom_728 ##.ad_bottom_leaderboard ##.ad_bottom_left ##.ad_bottom_mpu ##.ad_bottom_space ##.ad_bottomline ##.ad_box ##.ad_box1 ##.ad_box2 ##.ad_box_2 ##.ad_box_ad ##.ad_box_div ##.ad_box_new ##.ad_box_righ ##.ad_box_right_120 ##.ad_box_spacer ##.ad_box_title ##.ad_boxright1 ##.ad_break ##.ad_btf ##.ad_btf_300x250 ##.ad_btf_728x90 ##.ad_buttom_banner ##.ad_buttons_300 ##.ad_buttons_320 ##.ad_callout ##.ad_caption ##.ad_center ##.ad_center_bottom ##.ad_centered ##.ad_cheat ##.ad_choice ##.ad_choices ##.ad_claim ##.ad_click ##.ad_code ##.ad_col ##.ad_col_a ##.ad_column ##.ad_column_box ##.ad_column_hl ##.ad_common ##.ad_cont ##.ad_cont_footer ##.ad_contain ##.ad_container ##.ad_container_300x250 ##.ad_container_5 ##.ad_container_6 ##.ad_container_7 ##.ad_container_728x90 ##.ad_container_8 ##.ad_container_9 ##.ad_container__sidebar ##.ad_container__top ##.ad_container_body ##.ad_content ##.ad_content_wide ##.ad_contents ##.ad_custombanner ##.ad_db ##.ad_default ##.ad_deferrable ##.ad_description ##.ad_descriptor ##.ad_desktop ##.ad_disclaimer ##.ad_div_banner ##.ad_embed ##.ad_eniro ##.ad_entry_title_under ##.ad_entrylists_end ##.ad_eyebrow ##.ad_feature ##.ad_filler ##.ad_flash ##.ad_flat-boxright10 ##.ad_flat-boxright6 ##.ad_flat-boxright9 ##.ad_float ##.ad_font ##.ad_footer ##.ad_for_layout ##.ad_frame ##.ad_framed ##.ad_front_promo ##.ad_full_click ##.ad_fullwidth ##.ad_gal ##.ad_global_header ##.ad_gpt ##.ad_grid ##.ad_gutter_top ##.ad_half_page ##.ad_halfpage ##.ad_hat_728 ##.ad_hat_banner_300 ##.ad_hat_top ##.ad_head ##.ad_head_rectangle ##.ad_head_wide ##.ad_header ##.ad_header_lb ##.ad_header_left ##.ad_header_noad ##.ad_heading ##.ad_headline ##.ad_help_link ##.ad_holder ##.ad_home_block ##.ad_honcode_label ##.ad_hpm ##.ad_hr ##.ad_hyper_wrap ##.ad_identifier ##.ad_iframe2 ##.ad_ifrwrap ##.ad_image ##.ad_image_container ##.ad_img ##.ad_index02 ##.ad_indicator ##.ad_info_block ##.ad_inline ##.ad_inset ##.ad_island ##.ad_island2_spacer ##.ad_island_feedback ##.ad_island_spacer ##.ad_isolation ##.ad_item ##.ad_jnaught ##.ad_keywords_bot ##.ad_keywords_bot_r ##.ad_l ##.ad_label ##.ad_large ##.ad_launchpad ##.ad_leader ##.ad_leader_bottom ##.ad_leader_plus_top ##.ad_leaderboard ##.ad_leaderboard_top ##.ad_left_cell ##.ad_left_column ##.ad_lft ##.ad_line ##.ad_line2 ##.ad_link ##.ad_link1 ##.ad_link_468 ##.ad_link_area ##.ad_link_label ##.ad_link_label_vert ##.ad_links ##.ad_linkunit ##.ad_lnks ##.ad_loc ##.ad_lrec ##.ad_lt ##.ad_main ##.ad_margin ##.ad_masthead ##.ad_med ##.ad_medium_rectangle ##.ad_medrec ##.ad_medrect ##.ad_middle ##.ad_middle_banner ##.ad_middle_hub_page ##.ad_mobile ##.ad_mod ##.ad_module ##.ad_mp ##.ad_mpu ##.ad_mpu_top ##.ad_mr ##.ad_mrec ##.ad_mrec_title_article ##.ad_mrect ##.ad_mrectangle ##.ad_msg ##.ad_new_box01 ##.ad_new_box02 ##.ad_news ##.ad_newsstream ##.ad_no_border ##.ad_note ##.ad_notice ##.ad_nsRT_300_250 ##.ad_nsbd_300_250 ##.ad_one ##.ad_outer ##.ad_overlays ##.ad_p360 ##.ad_pagebody ##.ad_panel ##.ad_partner ##.ad_partners ##.ad_perma-panorama ##.ad_pic ##.ad_placeholder ##.ad_placement ##.ad_placement_300x250 ##.ad_placement_small ##.ad_plane_336 ##.ad_plus ##.ad_policy_link_br ##.ad_position ##.ad_post ##.ad_posttop ##.ad_power ##.ad_primary ##.ad_promo ##.ad_promo1 ##.ad_promo_spacer ##.ad_r ##.ad_rakuten ##.ad_rakuten_wrapper ##.ad_rec ##.ad_rect ##.ad_rect_contr ##.ad_rectangle ##.ad_rectangle_300_250 ##.ad_rectangle_medium ##.ad_rectangular ##.ad_regular1 ##.ad_regular2 ##.ad_regular3 ##.ad_reminder ##.ad_report_btn ##.ad_rightSky ##.ad_right_cell ##.ad_right_col ##.ad_right_column ##.ad_right_column160 ##.ad_rightside ##.ad_row ##.ad_row_bottom_item ##.ad_rtg300 ##.ad_secondary ##.ad_section_300x250 ##.ad_section_728x90 ##.ad_segment ##.ad_sense_01 ##.ad_sense_footer_container ##.ad_share_box ##.ad_shuffling_text ##.ad_side ##.ad_sidebar ##.ad_sidebar_bigbox ##.ad_size_160x600 ##.ad_sky ##.ad_skyscpr ##.ad_skyscraper ##.ad_skyscrapper ##.ad_slot ##.ad_slot_right ##.ad_slug ##.ad_slug_font ##.ad_slug_healthgrades ##.ad_slug_table ##.ad_small ##.ad_sonar ##.ad_space ##.ad_space_300_250 ##.ad_space_730 ##.ad_space_holder ##.ad_space_in ##.ad_space_rgt ##.ad_space_w300_h250 ##.ad_spacer ##.ad_special_badge ##.ad_spons_box ##.ad_sponsor ##.ad_sponsor_fp ##.ad_sponsoredlinks ##.ad_sponsoredsection ##.ad_spot ##.ad_spot_b ##.ad_spot_c ##.ad_square ##.ad_square_r ##.ad_square_r_top ##.ad_square_top ##.ad_story_island ##.ad_sub ##.ad_supersize ##.ad_swf ##.ad_tag ##.ad_tag_middle ##.ad_text ##.ad_text_link ##.ad_text_links ##.ad_text_vertical ##.ad_text_w ##.ad_textlink_box ##.ad_thumbnail_header ##.ad_title ##.ad_title_small ##.ad_tlb ##.ad_top ##.ad_top1 ##.ad_top_1 ##.ad_top_2 ##.ad_top_3 ##.ad_top_banner ##.ad_top_leaderboard ##.ad_top_left ##.ad_top_mpu ##.ad_top_right ##.ad_topic_content ##.ad_topright ##.ad_topshop ##.ad_tower ##.ad_trailer_header ##.ad_trick_header ##.ad_trick_left ##.ad_ttl ##.ad_type_adsense ##.ad_type_dfp ##.ad_under ##.ad_unit ##.ad_unit_300_x_250 ##.ad_unit_rail ##.ad_url ##.ad_v2 ##.ad_v3 ##.ad_v300 ##.ad_vertisement ##.ad_w300i ##.ad_w_us_a300 ##.ad_warn ##.ad_warning ##.ad_wid300 ##.ad_wide ##.ad_widget ##.ad_widget_200_100 ##.ad_widget_200_200 ##.ad_word ##.ad_wrap ##.ad_wrapper ##.ad_wrapper_false ##.ad_wrapper_fixed ##.ad_wrapper_top ##.ad_wrp ##.ad_zone ##.adamazon ##.adarea ##.adarea-long ##.adb-728x90 ##.adback ##.adbadge ##.adban-hold-narrow ##.adbanner ##.adbanner-300-250 ##.adbanner1 ##.adbanner2nd ##.adbannerbox ##.adbanneriframe ##.adbannerright ##.adbannertop ##.adbar ##.adbase ##.adbbox ##.adbckgrnd ##.adbetween ##.adblade ##.adblade-container ##.adbladeimg ##.adblk ##.adblock-240-400 ##.adblock-300-300 ##.adblock-600-120 ##.adblock-bottom ##.adblock-header ##.adblock-header1 ##.adblock-main ##.adblock-top ##.adblock-top-left ##.adblock-wide ##.adblock300 ##.adblock300250 ##.adblock300x250Spot1 ##.adblock728x90 ##.adblock_noborder ##.adblock_primary ##.adblocks-topright ##.adboard ##.adborder ##.adbot ##.adbot_postbit ##.adbot_showthread ##.adbottom ##.adbottomright ##.adbox-300x250 ##.adbox-468x60 ##.adbox-box ##.adbox-outer ##.adbox-rectangle ##.adbox-slider ##.adbox-title ##.adbox-topbanner ##.adbox-wrapper ##.adbox1 ##.adbox160 ##.adbox2 ##.adbox300 ##.adbox300x250 ##.adbox336 ##.adbox728 ##.adboxVert ##.adbox_300x600 ##.adbox_366x280 ##.adbox_468X60 ##.adbox_border ##.adbox_bottom ##.adbox_br ##.adbox_cont ##.adbox_largerect ##.adbox_left ##.adboxbg ##.adboxbot ##.adboxclass ##.adboxcontent ##.adboxes ##.adboxesrow ##.adboxlong ##.adboxo ##.adbreak ##.adbrite2 ##.adbrite_post ##.adbucks ##.adbug ##.adbutton ##.adbutton-block ##.adbuttons ##.adbygoogle ##.adcard ##.adcasing ##.adcenter ##.adchange ##.adchoices ##.adchoices-link ##.adclass ##.adcode ##.adcode2 ##.adcode_container ##.adcodetop ##.adcol1 ##.adcol2 ##.adcolumn ##.adcolumn_wrapper ##.adcomment ##.adcont ##.adcontent_box ##.adcopy ##.adctr ##.add-column2 ##.add-header-area ##.add-sidebar ##.add300 ##.add300top ##.add300x250 ##.add768 ##.addResources ##.add_300_250 ##.add_300x250 ##.add_728x90_teckpage ##.add_baner ##.add_topbanner ##.addarea ##.addarearight ##.addbanner ##.addboxRight ##.addiv ##.adds2 ##.adds300x250 ##.adds620x90 ##.addtitle ##.addvert ##.addwide ##.adengageadzone ##.adenquire ##.adexpl ##.adf_tisers ##.adfbox ##.adfeeds ##.adfieldbg ##.adfix ##.adfix-300x250 ##.adflag ##.adflexi ##.adfloatleft ##.adfloatright ##.adfoot ##.adfootbox ##.adfooter ##.adframe ##.adframe2 ##.adframe_banner ##.adframe_rectangle ##.adfree ##.adgear ##.adgear-bb ##.adgear_header ##.adgeletti-ad-div ##.adgoogle_block ##.adhalfhome ##.adhead ##.adhead_h ##.adhead_h_wide ##.adheader ##.adheader100 ##.adheader401 ##.adheader416 ##.adherebox ##.adhi ##.adhide ##.adhint ##.adholder ##.adholder-300 ##.adholderban ##.adhoriz ##.adhref_box_ads ##.adical_contentad ##.adiframe ##.adinfo ##.adinjwidget ##.adinner ##.adinsert ##.adinsert-bdr ##.adinsert160 ##.adinside ##.adintro ##.adits ##.adjlink ##.adkicker ##.adkit ##.adkit-advert ##.adkit-lb-footer ##.adkit_free_html ##.adl125 ##.adlabel-horz ##.adlabel-vert ##.adlabelleft ##.adlarge ##.adlarger ##.adlayer ##.adleader ##.adleft1 ##.adline ##.adlink ##.adlinkdiv ##.adlinks ##.adlinks-class ##.adlist ##.adlist1 ##.adlist2 ##.adlnklst ##.adlsot ##.admain ##.adman ##.admaster ##.admediumred ##.admedrec ##.admeldBoxAd ##.admessage ##.admiddle ##.admiddlesidebar ##.administer-ad ##.admods ##.admodule ##.admoduleB ##.admpu ##.admpu-small ##.admz ##.adnation-banner ##.adnet120 ##.adnet_area ##.adnotecenter ##.adnotice ##.adocean728x90 ##.adonmedianama ##.adops ##.adp-AdPrefix ##.adpacks ##.adpacks_content ##.adpad300 ##.adpad300spacer ##.adpadding ##.adpadtwo_div ##.adpane ##.adpic ##.adplace ##.adplace_center ##.adplacement ##.adplate-background ##.adpod ##.adpos-19 ##.adpos-20 ##.adpos-25 ##.adpos-26 ##.adpos-8 ##.adpost ##.adproxy ##.adrec ##.adrect ##.adrectangle ##.adrectwrapper ##.adright ##.adright300 ##.adrightsm ##.adrighttop ##.adriverBanner ##.adroot ##.adrotate_widget ##.adrow ##.adrow-post ##.adrow1 ##.adrow1box1 ##.adrow1box3 ##.adrow1box4 ##.adrow2 ##.adrule ##.ads--sidebar ##.ads-1 ##.ads-120x600 ##.ads-125 ##.ads-125-widget ##.ads-160-head ##.ads-160x600 ##.ads-160x600-outer ##.ads-166-70 ##.ads-180-65 ##.ads-2 ##.ads-220x90 ##.ads-250 ##.ads-290 ##.ads-3 ##.ads-300 ##.ads-300-250 ##.ads-300-box ##.ads-300x250 ##.ads-300x300 ##.ads-300x80 ##.ads-336-197-qu ##.ads-468 ##.ads-468x60-bordered ##.ads-560-65 ##.ads-600-box ##.ads-728-90 ##.ads-728by90 ##.ads-728x90 ##.ads-728x90-wrap ##.ads-above-comments ##.ads-ad ##.ads-ads-top ##.ads-area ##.ads-articlebottom ##.ads-banner ##.ads-banner-bottom ##.ads-banner-js ##.ads-banner-middle ##.ads-banner-top-right ##.ads-beforecontent ##.ads-below-content ##.ads-below-home ##.ads-bg ##.ads-bigbox ##.ads-block ##.ads-block-bottom-wrap ##.ads-block-link-000 ##.ads-block-link-text ##.ads-block-marketplace-container ##.ads-border ##.ads-bottom ##.ads-bottom-block ##.ads-box ##.ads-box-border ##.ads-box-header ##.ads-box-header-marketplace-right ##.ads-box-header-pb ##.ads-box-header-ws ##.ads-box-header-wsl ##.ads-btm ##.ads-by ##.ads-by-google-0 ##.ads-card ##.ads-cars-larger ##.ads-cars-top2 ##.ads-categories-bsa ##.ads-col ##.ads-container-mediumrectangle ##.ads-content ##.ads-custom ##.ads-divider ##.ads-favicon ##.ads-fieldset ##.ads-fif ##.ads-flow ##.ads-footer ##.ads-google ##.ads-half ##.ads-header ##.ads-here ##.ads-holder ##.ads-home-top-buttons-wrap ##.ads-horizontal ##.ads-horizontal-banner ##.ads-inarticle ##.ads-inline ##.ads-item ##.ads-label ##.ads-leaderboard ##.ads-leaderboard-border ##.ads-left ##.ads-line ##.ads-links-general ##.ads-long ##.ads-main ##.ads-margin ##.ads-medium-rect ##.ads-middle ##.ads-middle-top ##.ads-mini ##.ads-module ##.ads-movie ##.ads-mpu ##.ads-native-wrapper ##.ads-note ##.ads-outer ##.ads-player-03 ##.ads-popup-corner ##.ads-post ##.ads-post-closing ##.ads-post-full ##.ads-profile ##.ads-rectangle ##.ads-right ##.ads-right-min ##.ads-rotate ##.ads-scroller-box ##.ads-section ##.ads-side ##.ads-sidebar ##.ads-sidebar-boxad ##.ads-single ##.ads-site ##.ads-sky ##.ads-small ##.ads-sponsors ##.ads-sponsors-125-left ##.ads-sponsors-125-right ##.ads-square ##.ads-squares ##.ads-story ##.ads-stripe ##.ads-text ##.ads-title ##.ads-top ##.ads-top-spacer ##.ads-ul ##.ads-wide ##.ads-widget ##.ads-widget-partner-gallery ##.ads-widget-sponsor-gallery ##.ads-wrapper ##.ads-zone ##.ads01 ##.ads02 ##.ads03 ##.ads04 ##.ads05 ##.ads06 ##.ads07 ##.ads08 ##.ads09 ##.ads1 ##.ads10 ##.ads1000x100 ##.ads11 ##.ads12 ##.ads120_600 ##.ads120_600-widget ##.ads120_80 ##.ads120x ##.ads123 ##.ads125 ##.ads125-widget ##.ads13 ##.ads14 ##.ads15 ##.ads160 ##.ads160-600 ##.ads160_600-widget ##.ads160x600 ##.ads180x150 ##.ads1_250 ##.ads1_label ##.ads24Block ##.ads250-250 ##.ads250_250-widget ##.ads250_96 ##.ads3 ##.ads300 ##.ads300-200 ##.ads300-250 ##.ads300250 ##.ads300_250 ##.ads300_250-widget ##.ads300_600-widget ##.ads300box ##.ads300n ##.ads300nb ##.ads300x ##.ads300x100 ##.ads300x250 ##.ads300x250-thumb ##.ads315 ##.ads320x100 ##.ads324-wrapper ##.ads324-wrapper2ads ##.ads336_280 ##.ads336x280 ##.ads4 ##.ads460 ##.ads460_home ##.ads468 ##.ads468x60 ##.ads486x100 ##.ads486x100-1 ##.ads598x98 ##.ads5blocks ##.ads667x100 ##.ads720x90 ##.ads728 ##.ads728_90 ##.ads728x90 ##.ads728x90-1 ##.ads728x90-thumb ##.ads970 ##.adsArea ##.adsBelowHeadingNormal ##.adsBlock ##.adsBot ##.adsBottom ##.adsBox ##.adsBoxTop ##.adsCategoryIcon ##.adsCategoryTitleLink ##.adsCell ##.adsCont ##.adsDef ##.adsDisclaimer ##.adsDiv ##.adsFull ##.adsHeader ##.adsHeaderFlog ##.adsHeading ##.adsImages ##.adsInner ##.adsInsideResults_v3 ##.adsLabel ##.adsLibrary ##.adsLine ##.adsMPU ##.adsMiddle ##.adsOuter ##.adsOverPrimary ##.adsRectangleMedium ##.adsRight ##.adsRow ##.adsSpacing ##.adsTableBlox ##.adsTag ##.adsText ##.adsTextHouse ##.adsThema ##.adsTop ##.adsTopBanner ##.adsTopCont ##.adsTower2 ##.adsTowerWrap ##.adsWidget ##.adsWithUs ##.adsYN ##.ads_1 ##.ads_120x60 ##.ads_120x60_index ##.ads_125_square ##.ads_160 ##.ads_180 ##.ads_2 ##.ads_3 ##.ads_300 ##.ads_300250_wrapper ##.ads_300x100 ##.ads_300x239 ##.ads_300x250 ##.ads_300x600 ##.ads_305 ##.ads_320 ##.ads_320_100 ##.ads_330 ##.ads_337x280 ##.ads_3col ##.ads_4 ##.ads_460up ##.ads_468 ##.ads_468x60 ##.ads_672 ##.ads_728 ##.ads_728x90 ##.ads_admeld ##.ads_after ##.ads_after_more ##.ads_amazon ##.ads_amazon_outer ##.ads_area ##.ads_article ##.ads_banner ##.ads_banner_between ##.ads_banner_between_string ##.ads_bar ##.ads_before ##.ads_bg ##.ads_big ##.ads_big-half ##.ads_big_right ##.ads_big_right_code ##.ads_bigrec ##.ads_block ##.ads_block250 ##.ads_border ##.ads_box ##.ads_box_headline ##.ads_brace ##.ads_by ##.ads_by_tico ##.ads_catDiv ##.ads_catDivRight ##.ads_code ##.ads_column ##.ads_container ##.ads_der ##.ads_disc_anchor ##.ads_disc_leader ##.ads_disc_lwr_square ##.ads_disc_rectangle ##.ads_disc_skyscraper ##.ads_disc_square ##.ads_div ##.ads_entrymore ##.ads_folat_left ##.ads_foot ##.ads_footer ##.ads_footerad ##.ads_frame_wrapper ##.ads_google ##.ads_h ##.ads_header ##.ads_header_bottom ##.ads_holder ##.ads_horizontal ##.ads_infoBtns ##.ads_inside2 ##.ads_item ##.ads_layout_sky ##.ads_lb ##.ads_leader ##.ads_leaderboard ##.ads_left ##.ads_loc_bottom ##.ads_loc_side ##.ads_lr_wrapper ##.ads_lr_wrapper2 ##.ads_main ##.ads_main_hp ##.ads_medrect ##.ads_middle ##.ads_middle_container ##.ads_mpu ##.ads_mpu_small ##.ads_obrazek ##.ads_outer ##.ads_outline ##.ads_post ##.ads_post_end ##.ads_post_end_code ##.ads_post_start ##.ads_post_start_code ##.ads_r ##.ads_rectangle ##.ads_rem ##.ads_remove ##.ads_right ##.ads_rightbar_top ##.ads_sc_bl ##.ads_sc_bl_i ##.ads_sc_ls_i ##.ads_sc_tb ##.ads_sc_tl_i ##.ads_sep ##.ads_show_if ##.ads_side ##.ads_sideba ##.ads_sidebar ##.ads_sidebar_360 ##.ads_sidebar_360_b ##.ads_singlepost ##.ads_slice ##.ads_small_rectangle ##.ads_space_long ##.ads_spacer ##.ads_square ##.ads_takeover ##.ads_text ##.ads_ticker_main ##.ads_title ##.ads_top ##.ads_top_both ##.ads_top_promo ##.ads_topbanner ##.ads_topleft ##.ads_topright ##.ads_tower ##.ads_tr ##.ads_under_fileinfo ##.ads_under_player ##.ads_up ##.ads_up_big2 ##.ads_verticalSpace ##.ads_vtlLink ##.ads_vtlList ##.ads_wide ##.ads_widesky ##.ads_without_height ##.ads_wrapper ##.ads_wrapperads_top ##.adsafp ##.adsanity-group ##.adsarea ##.adsbantop ##.adsbar ##.adsbg300 ##.adsblock ##.adsblockvert ##.adsbnr ##.adsbody ##.adsborder ##.adsbottom ##.adsbottombox ##.adsbox ##.adsbox-square ##.adsboxBtn ##.adsbox_300x250 ##.adsboxitem ##.adsbttmpg ##.adsbygoogle ##.adsbygoogle-box ##.adsbygoogle2 ##.adsbysinodia ##.adsbyyahoo ##.adsc ##.adscaleAdvert ##.adscaleP6_canvas ##.adscaleTop ##.adscatalog ##.adsclick ##.adscontainer ##.adscontent250 ##.adscontentcenter ##.adscreen ##.adsd_shift100 ##.adsdisplaygames ##.adsdiv ##.adsection_a2 ##.adsection_c2 ##.adsection_c3 ##.adsence-domain ##.adsens ##.adsense-250 ##.adsense-300x256-widget ##.adsense-300x256-widget-2 ##.adsense-336 ##.adsense-468 ##.adsense-ad ##.adsense-ads ##.adsense-afterpost ##.adsense-attribution ##.adsense-block ##.adsense-category ##.adsense-category-bottom ##.adsense-center ##.adsense-code ##.adsense-container ##.adsense-div ##.adsense-float ##.adsense-googleAds ##.adsense-header ##.adsense-heading ##.adsense-image-detail ##.adsense-left ##.adsense-links ##.adsense-links2 ##.adsense-mod-border ##.adsense-module ##.adsense-overlay ##.adsense-post ##.adsense-review ##.adsense-reviews-float ##.adsense-right ##.adsense-slot ##.adsense-square ##.adsense-title ##.adsense-top ##.adsense-top-bar ##.adsense-topics-detail ##.adsense-unit ##.adsense-wide-background ##.adsense-widget ##.adsense-widget-horizontal ##.adsense1 ##.adsense160x600 ##.adsense250 ##.adsense3 ##.adsense300 ##.adsense728 ##.adsense728x90 ##.adsenseAds ##.adsenseBlock ##.adsenseContainer ##.adsenseGreenBox ##.adsenseInPost ##.adsenseLargeRectangle ##.adsenseList ##.adsenseRow ##.adsenseSky ##.adsenseWrapper ##.adsense_200 ##.adsense_200x200 ##.adsense_728x15_center ##.adsense_bdc_v2 ##.adsense_block ##.adsense_bottom ##.adsense_box01 ##.adsense_container ##.adsense_div_wrapper ##.adsense_full_width ##.adsense_leader ##.adsense_left_lu ##.adsense_mainbox01 ##.adsense_managed ##.adsense_managed_ ##.adsense_media ##.adsense_menu ##.adsense_mpu ##.adsense_rectangle ##.adsense_results ##.adsense_right ##.adsense_sidebar ##.adsense_single ##.adsense_small_square ##.adsense_top ##.adsense_top_ad ##.adsense_top_lu ##.adsense_x88 ##.adsensebig ##.adsenseblock_bottom ##.adsenseblock_top ##.adsenseformat ##.adsenseframe ##.adsenseleaderboard ##.adsenselr ##.adsensem_widget ##.adsensemainpage ##.adsensesky ##.adsensesq ##.adsensex336 ##.adsenvelope ##.adsep ##.adseparator ##.adserve_728 ##.adserver_zone ##.adset ##.adsforums ##.adsghori ##.adsgrd ##.adsgvert ##.adshome ##.adshowcase ##.adshp ##.adside ##.adside-box-index ##.adside-box-single ##.adsidebar ##.adsidebox ##.adsider ##.adsincs2 ##.adsinfo ##.adsingle ##.adsitem ##.adsize728 ##.adsizer ##.adsleaderboard ##.adsleaderboardbox ##.adsleft ##.adsleftblock ##.adslibraryArticle ##.adslider ##.adslink ##.adslist ##.adslogan ##.adslot ##.adslot-mpu ##.adslot-widget ##.adslot_1 ##.adslot_300 ##.adslot_728 ##.adslot_blurred ##.adslot_bot_300x250 ##.adslothead ##.adslotleft ##.adslotright ##.adslug ##.adsmall ##.adsmaller ##.adsmalltext ##.adsmanag ##.adsmedrect ##.adsmedrectright ##.adsmessage ##.adsnippet_widget ##.adsns ##.adsonar-after ##.adspace ##.adspace-300x600 ##.adspace-MR ##.adspace-leaderboard ##.adspace-mpu ##.adspace-widget ##.adspace1 ##.adspace180 ##.adspace2 ##.adspace728x90 ##.adspace_2 ##.adspace_bottom ##.adspace_buysell ##.adspace_rotate ##.adspace_skyscraper ##.adspace_top ##.adspacer ##.adspan ##.adspanel ##.adspecial390 ##.adspeed ##.adsplash-160x600 ##.adsplat ##.adspost ##.adspot ##.adspot-title ##.adspot1 ##.adspot200x90 ##.adspot468x60 ##.adspot728x90 ##.adspot_468x60 ##.adspot_728x90 ##.adsrecnode ##.adsskyscraper ##.adssmall ##.adssquare ##.adssquare2 ##.adstext ##.adstextpad ##.adstipt ##.adstitle ##.adstop ##.adstory ##.adstrip ##.adstxt ##.adstyle ##.adsupperugo ##.adsupperugo_txt ##.adswidget ##.adswitch ##.adsxpls ##.adsystem_ad ##.adszone ##.adtab ##.adtable ##.adtag ##.adtech ##.adtech-ad-widget ##.adtech-banner ##.adtech-boxad ##.adtext_gray ##.adtext_horizontal ##.adtext_onwhite ##.adtext_vertical ##.adtext_white ##.adtextleft ##.adtextright ##.adtexts ##.adtile ##.adtips ##.adtips1 ##.adtoggle ##.adtop ##.adtop-border ##.adtops ##.adtower ##.adtravel ##.adtv_300_250 ##.adtxt ##.adtxtlinks ##.adult-adv ##.adunit ##.adunit-300-250 ##.adunit-active ##.adunit-middle ##.adunit-parent ##.adunit125 ##.adunit160 ##.adunit300x250 ##.adunit468 ##.adunit_210x509 ##.adunit_300x100 ##.adunit_300x250 ##.adunit_300x600 ##.adunit_607x110 ##.adunit_728x90 ##.adunit_content ##.adunit_footer ##.adunit_maincol_right ##.adv-160 ##.adv-200-200 ##.adv-250-250 ##.adv-300 ##.adv-300-1 ##.adv-300-250 ##.adv-300x250 ##.adv-336-280 ##.adv-4 ##.adv-468-60 ##.adv-700 ##.adv-970 ##.adv-ad ##.adv-background ##.adv-banner ##.adv-block ##.adv-border ##.adv-bottom ##.adv-box ##.adv-box-wrapper ##.adv-click ##.adv-cont ##.adv-container ##.adv-dvb ##.adv-format-1 ##.adv-google ##.adv-halfpage ##.adv-intext ##.adv-intext-label ##.adv-key ##.adv-label ##.adv-leaderboard ##.adv-leaderboard-banner ##.adv-mpu ##.adv-outer ##.adv-p ##.adv-right ##.adv-right-300 ##.adv-search-ad ##.adv-sidebar ##.adv-slide-block-wrapper ##.adv-square-banner ##.adv-squarebox-banner ##.adv-teaser-divider ##.adv-top ##.adv-top-container ##.adv-x61 ##.adv200 ##.adv250 ##.adv300 ##.adv300-250 ##.adv300-250-2 ##.adv300-70 ##.adv300left ##.adv300x100 ##.adv300x250 ##.adv300x70 ##.adv336 ##.adv350 ##.adv460x60 ##.adv468 ##.adv468x90 ##.adv728 ##.advBottom ##.advBottomHome ##.advBox ##.advImagesbox ##.advLB_PageMiddle ##.advLeaderboard ##.advSquare ##.advText ##.advVideobox ##.adv_1 ##.adv_120 ##.adv_120_600 ##.adv_120x240 ##.adv_120x600 ##.adv_160_600 ##.adv_160x600 ##.adv_2 ##.adv_250_250 ##.adv_300 ##.adv_300_300 ##.adv_300_top ##.adv_300x250 ##.adv_336_280 ##.adv_468_60 ##.adv_630 ##.adv_728_90 ##.adv_728x90 ##.adv_90 ##.adv_PageTop ##.adv_aff ##.adv_banner ##.adv_banner_hor ##.adv_bg ##.adv_box_narrow ##.adv_cnt ##.adv_code ##.adv_default_box_container ##.adv_flash ##.adv_headerleft ##.adv_headerright ##.adv_hed ##.adv_here ##.adv_in_body_a ##.adv_info_text ##.adv_leaderboard ##.adv_left ##.adv_link ##.adv_main_middle ##.adv_main_middle_wrapper ##.adv_main_right_down ##.adv_main_right_down_wrapper ##.adv_medium_rectangle ##.adv_panel ##.adv_pointer_home ##.adv_pointer_section ##.adv_right ##.adv_sd_dx ##.adv_side1 ##.adv_side2 ##.adv_sidebar ##.adv_sidebar_300x250 ##.adv_top ##.adv_underpost ##.adv_x_1 ##.adv_x_2 ##.advbanner_300x250 ##.advbanner_300x600 ##.advbanner_970x90 ##.advbig ##.advbptxt ##.adver ##.adver-left ##.adver-text ##.adverTag ##.adverTxt ##.adver_bot ##.adver_cont_below ##.adverdown ##.adverhrz ##.adverserve145 ##.adverstisement_right ##.advert--banner-wrap ##.advert--mpu ##.advert--mpu--rhs ##.advert--vc ##.advert--vc__wrapper ##.advert-100 ##.advert-120x90 ##.advert-160x600 ##.advert-300 ##.advert-300-side ##.advert-300x100-side ##.advert-300x250-container ##.advert-728 ##.advert-728-90 ##.advert-728x90 ##.advert-760 ##.advert-arch-top ##.advert-article-bottom ##.advert-banner ##.advert-banner-holder ##.advert-bannerad ##.advert-bg-250 ##.advert-block ##.advert-bloggrey ##.advert-body-not-home ##.advert-bot-box ##.advert-box ##.advert-btm ##.advert-center ##.advert-center_468x60 ##.advert-col-center ##.advert-competitions ##.advert-container ##.advert-content ##.advert-content-item ##.advert-detail ##.advert-featured ##.advert-footer ##.advert-full-raw ##.advert-group ##.advert-head ##.advert-header-728 ##.advert-home-380x120 ##.advert-horizontal ##.advert-iab-300-250 ##.advert-iab-468-60 ##.advert-label ##.advert-leaderboard ##.advert-leaderboard2 ##.advert-loader ##.advert-lower-right ##.advert-mini ##.advert-mpu ##.advert-mrec ##.advert-note ##.advert-overlay ##.advert-pane ##.advert-right ##.advert-section ##.advert-sky ##.advert-skyscraper ##.advert-stub ##.advert-text ##.advert-three ##.advert-tile ##.advert-title ##.advert-top ##.advert-top-footer ##.advert-txt ##.advert-under-hedaer ##.advert-unit ##.advert-wide ##.advert-words ##.advert-wrap ##.advert-wrap1 ##.advert-wrap2 ##.advert-wrapper ##.advert1 ##.advert120 ##.advert1Banner ##.advert2 ##.advert300 ##.advert300-home ##.advert300x250 ##.advert300x300 ##.advert300x440 ##.advert300x600 ##.advert350ih ##.advert4 ##.advert5 ##.advert728_90 ##.advert728x90 ##.advert8 ##.advertBanner ##.advertBar ##.advertBlock ##.advertBottom ##.advertBox ##.advertCaption ##.advertColumn ##.advertCont ##.advertContainer ##.advertContent ##.advertFullBanner ##.advertGenerator ##.advertHeadline ##.advertIslandWrapper ##.advertLink ##.advertLink1 ##.advertRight ##.advertSideBar ##.advertSign ##.advertSuperBanner ##.advertText ##.advertTitleSky ##.advert_300x250 ##.advert_336 ##.advert_468x60 ##.advert__container ##.advert_area ##.advert_back_160x600 ##.advert_back_300x250 ##.advert_back_300xXXX ##.advert_banner ##.advert_block ##.advert_box ##.advert_cont ##.advert_container ##.advert_div ##.advert_djad ##.advert_google_content ##.advert_google_title ##.advert_header ##.advert_home_300 ##.advert_img ##.advert_in_post ##.advert_label ##.advert_leaderboard ##.advert_line ##.advert_list ##.advert_main ##.advert_main_bottom ##.advert_mpu_body_hdr ##.advert_nav ##.advert_note ##.advert_small ##.advert_societe_general ##.advert_source ##.advert_surr ##.advert_top ##.advert_txt ##.advert_wrapper ##.advertasingtxt ##.advertbar ##.advertbox ##.advertheader-red ##.adverthome ##.advertis-left ##.advertis-right ##.advertise-box ##.advertise-here ##.advertise-homestrip ##.advertise-horz ##.advertise-info ##.advertise-inquiry ##.advertise-leaderboard ##.advertise-link ##.advertise-link-post-bottom ##.advertise-list ##.advertise-small ##.advertise-square ##.advertise-top ##.advertise-vert ##.advertiseBlack ##.advertiseContainer ##.advertiseHere ##.advertiseLabel234x60 ##.advertiseLabel300x250 ##.advertiseText ##.advertise_ads ##.advertise_box ##.advertise_box1 ##.advertise_box4 ##.advertise_here ##.advertise_link ##.advertise_link_sidebar ##.advertise_links ##.advertise_sec ##.advertise_txt ##.advertise_verRight ##.advertisebtn ##.advertisedBy ##.advertisement-1 ##.advertisement-160-600 ##.advertisement-2 ##.advertisement-234-60 ##.advertisement-300-250 ##.advertisement-300x250 ##.advertisement-300x600 ##.advertisement-728-90 ##.advertisement-728x90 ##.advertisement-750-60 ##.advertisement-BottomRight ##.advertisement-after ##.advertisement-background ##.advertisement-banner ##.advertisement-before ##.advertisement-bkg ##.advertisement-block ##.advertisement-bottom ##.advertisement-caption ##.advertisement-content ##.advertisement-copy ##.advertisement-dashed ##.advertisement-header ##.advertisement-label ##.advertisement-label-up-white ##.advertisement-layout ##.advertisement-leader-board ##.advertisement-leader-board-second ##.advertisement-leaderboard ##.advertisement-nav ##.advertisement-other ##.advertisement-placeholder ##.advertisement-position1 ##.advertisement-right ##.advertisement-right-rail ##.advertisement-sidebar ##.advertisement-space ##.advertisement-sponsor ##.advertisement-swimlane ##.advertisement-tag ##.advertisement-text ##.advertisement-top ##.advertisement-txt ##.advertisement-wrapper ##.advertisement1 ##.advertisement300x250 ##.advertisement468 ##.advertisementBackground ##.advertisementBannerVertical ##.advertisementBar ##.advertisementBlock ##.advertisementBox ##.advertisementCenterer ##.advertisementColumnGroup ##.advertisementContainer ##.advertisementFull ##.advertisementGif ##.advertisementHeader ##.advertisementImg ##.advertisementLabel ##.advertisementLabelFooter ##.advertisementOutsider ##.advertisementPanel ##.advertisementReloadable ##.advertisementRotate ##.advertisementSmall ##.advertisementText ##.advertisementTop ##.advertisement_160x600 ##.advertisement_300x250 ##.advertisement_below_news_article ##.advertisement_block_234_60 ##.advertisement_block_468_60 ##.advertisement_btm ##.advertisement_caption ##.advertisement_container ##.advertisement_flag ##.advertisement_flag_sky ##.advertisement_g ##.advertisement_header ##.advertisement_horizontal ##.advertisement_post ##.advertisement_river ##.advertisement_sky ##.advertisement_top ##.advertisement_watchFooter ##.advertisementonblue ##.advertisementonwhite ##.advertisements-right ##.advertisementsOutterDiv ##.advertisements_contain ##.advertisementsubtitle ##.advertiser ##.advertiser-links ##.advertisesingle ##.advertisespace_div ##.advertising-aside-top ##.advertising-banner ##.advertising-block ##.advertising-box-top-teaser ##.advertising-content ##.advertising-fixed ##.advertising-header ##.advertising-leaderboard ##.advertising-local-links ##.advertising-lrec ##.advertising-mention ##.advertising-srec ##.advertising-top ##.advertising-top-box ##.advertising-top-category ##.advertising160 ##.advertising2 ##.advertising300_home ##.advertising300x250 ##.advertising728 ##.advertising728_3 ##.advertisingBanner ##.advertisingBlock ##.advertisingBlocks ##.advertisingLegend ##.advertisingLrec ##.advertisingTable ##.advertising_300x250 ##.advertising_banner ##.advertising_block ##.advertising_bottom_box ##.advertising_box_bg ##.advertising_images ##.advertising_widget ##.advertisment ##.advertisment-label ##.advertisment-left-panal ##.advertisment-module ##.advertisment-top ##.advertismentBox ##.advertismentContainer ##.advertismentContent ##.advertismentText ##.advertisment_bar ##.advertisment_caption ##.advertisment_full ##.advertisment_two ##.advertize ##.advertize_here ##.advertlabel ##.advertleft ##.advertnotice ##.advertorial ##.advertorial-2 ##.advertorial-promo-box ##.advertorial-wrapper ##.advertorial2 ##.advertorial_728x90 ##.advertorial_red ##.advertorialitem ##.advertorialtitle ##.advertorialview ##.advertorialwidget ##.advertplay ##.adverts ##.adverts-125 ##.adverts_RHS ##.adverttext ##.adverttop ##.advfrm ##.advhere ##.advimg160600 ##.advimg300250 ##.advrectangle ##.advslideshow ##.advspot ##.advt ##.advt-banner-3 ##.advt-block ##.advt-sec ##.advt300 ##.advt720 ##.advtBlock ##.advt_160x600 ##.advt_468by60px ##.advt_indieclick ##.advt_single ##.advt_widget ##.advtext ##.advtimg ##.advtitle ##.advtop ##.advtop-leaderbord ##.advttopleft ##.adwhitespace ##.adwide ##.adwolf-holder ##.adword-box ##.adword-structure ##.adword-text ##.adword-title ##.adword1 ##.adwordListings ##.adwords ##.adwords-container ##.adwordsHeader ##.adwords_in_content ##.adwrap ##.adwrap-widget ##.adwrapper-lrec ##.adwrapper1 ##.adwrapper948 ##.adxli ##.adz728x90 ##.adzone ##.adzone-footer ##.adzone-sidebar ##.adzone_ad_5 ##.adzone_ad_6 ##.adzone_ad_7 ##.adzone_ad_8 ##.adzone_ad_9 ##.afc-box ##.afffix-custom-ad ##.affiliate-ad ##.affiliate-footer ##.affiliate-link ##.affiliate-mrec-iframe ##.affiliate-sidebar ##.affiliate-strip ##.affiliateAdvertText ##.affiliate_ad ##.affiliate_header_ads ##.affiliate_header_ads_container ##.affiliates-sidebar ##.affiliation728x90 ##.affinityAdHeader ##.afns-ad-sponsor-logo ##.afsAdvertising ##.afsAdvertisingBottom ##.afs_ads ##.aftContentAdLeft ##.aftContentAdRight ##.after-post-ad ##.after_ad ##.after_comments_ads ##.after_post_ad ##.afterpostadbox ##.agi-adsaleslinks ##.agi-adtop ##.aisle-ad ##.aisoad ##.ajaxads ##.al-wss-ad ##.alb-content-ad ##.alignads ##.allpages_ad_bottom ##.allpages_ad_top ##.alt-ad-box ##.alt_ad ##.alternatives_ad ##.amAdvert ##.am_ads ##.amsSparkleAdWrapper ##.anchor-ad-wrapper ##.anchorAd ##.annonce_textads ##.annons_themeBlock ##.annonstext ##.another_text_ad ##.answer_ad_content ##.aol-knot-fullscreen-right-ad ##.aol-twist-flyout-ad ##.aolSponsoredLinks ##.aopsadvert ##.ap_str_ad ##.apiAdMarkerAbove ##.apiAds ##.apiButtonAd ##.app-advertisements ##.app_advertising_skyscraper ##.apxContentAd ##.archive-ad ##.archive-ads ##.area1_2_ad1 ##.area5_ad ##.areaAd ##.aroundAdUnit ##.artAdInner ##.art_ads ##.art_new_ads_468_60 ##.artcl_promo_ad ##.article-ad ##.article-ad-300x250 ##.article-ad-box ##.article-ad-cont ##.article-ad-left ##.article-ad-main ##.article-ad-primary ##.article-ads ##.article-aside-ad ##.article-content-adwrap ##.article-header-ad ##.articleAd ##.articleAd300x250 ##.articleAdBlade ##.articleAdSlot2 ##.articleAdTop ##.articleAdTopRight ##.articleAds ##.articleAdsL ##.articleAdvert ##.articleEmbeddedAdBox ##.articleFooterAd ##.articleHeadAdRow ##.articleTopAd ##.article_ad ##.article_ad250 ##.article_ad_container2 ##.article_adbox ##.article_ads_banner ##.article_bottom_ad ##.article_google_ads ##.article_inline_ad ##.article_inner_ad ##.article_middle_ad ##.article_mpu_box ##.article_page_ads_bottom ##.article_sponsored_links ##.article_tower_ad ##.articlead ##.articleads ##.articlebodyad ##.articlepage_ads_1 ##.articlepage_ads_top ##.artist-ad-wrapper ##.as_ad ##.aseadn ##.aside-ad-wrapper ##.aside-ads ##.aside_AD01 ##.aside_AD02 ##.aside_AD06 ##.aside_AD08 ##.aside_AD09 ##.aside_banner_ads ##.aside_google_ads ##.associated-ads ##.atf-ad-medRect ##.atf-ad-medrec ##.atf_ad_box ##.attachment-sidebar-ad ##.attachment-sidebarAd ##.attachment-sidebar_ad ##.attachment-squareAd ##.attachment-weather-header-ad ##.auction-nudge ##.autoshow-top-ad ##.aux-ad-widget-1 ##.aux-ad-widget-2 ##.avertissement-download ##.b-ad ##.b-ad-footerBanner ##.b-ad-topBanner ##.b-ads728 ##.b-ads_300 ##.b-ads_gpt ##.b-ads_iframe ##.b-adsuniversal-wrap ##.b-advert ##.b-advert__grid ##.b-aside-ads ##.b-astro-sponsored-links_horizontal ##.b-astro-sponsored-links_vertical ##.b5-ad-pushdown ##.b5_widget_skyscraper_ad ##.b5ad_bigbox ##.b5ad_skyscraper ##.b_ad ##.b_ads ##.b_ads_cont ##.b_ads_r ##.b_ads_top ##.back300ad ##.backgroundAd ##.bads300 ##.badxcn ##.bam-dcRefreshableAd ##.ban-720-container ##.ban300side ##.ban420x200 ##.ban420x260 ##.ban680x450 ##.ban728 ##.ban980x90 ##.bank-rate-ad ##.banmanad ##.banner-125 ##.banner-300 ##.banner-300x250 ##.banner-300x600 ##.banner-468 ##.banner-468-60 ##.banner-468x60 ##.banner-728 ##.banner-728x90 ##.banner-ad ##.banner-ad-300x250 ##.banner-ad-footer ##.banner-ad-row ##.banner-ad-space ##.banner-ad-wrapper ##.banner-ads ##.banner-ads-300x250 ##.banner-ads-sidebar ##.banner-adsense ##.banner-adv ##.banner-advert ##.banner-adverts ##.banner-buysellads ##.banner-paid-ad-label ##.banner-rectangleMedium ##.banner-sidebar-300x250 ##.banner-top-ads ##.banner-top-banner-728x90 ##.banner1-728x90 ##.banner120x600 ##.banner125x125 ##.banner160 ##.banner160x600 ##.banner250_250 ##.banner300 ##.banner300by250 ##.banner336 ##.banner336x280 ##.banner350 ##.banner468 ##.banner468by60 ##.banner728 ##.banner728-ad ##.banner728-container ##.banner728x90 ##.bannerADV ##.bannerAd ##.bannerAd3 ##.bannerAd300x250 ##.bannerAdContainer ##.bannerAdLeaderboard ##.bannerAdRectangle ##.bannerAdSidebar ##.bannerAdTower ##.bannerAdWrap ##.bannerAdWrapper300x250 ##.bannerAdWrapper730x86 ##.bannerAd_rdr ##.bannerAds ##.bannerAdvert ##.bannerAside ##.bannerGAd ##.bannerRightAd ##.bannerTopAdLeft ##.bannerTopAdRight ##.bannerWrapAdwords ##.banner_160x600 ##.banner_250x250 ##.banner_300_250 ##.banner_300x250 ##.banner_300x250_2 ##.banner_300x250_3 ##.banner_468_60 ##.banner_468x60 ##.banner_728_90 ##.banner_728x90 ##.banner_ad ##.banner_ad-728x90 ##.banner_ad_233x90 ##.banner_ad_728x90 ##.banner_ad_footer ##.banner_ad_leaderboard ##.banner_ads ##.banner_ads1 ##.banner_adv ##.banner_mpu_integrated ##.banner_reklam ##.banner_reklam2 ##.banner_slot ##.bannerad ##.bannerad-125tower ##.bannerad-468x60 ##.banneradbottomholder ##.banneradd ##.bannerads ##.banneradv ##.bannerandads ##.bannergoogle ##.bannergroup-ads ##.banneritem-ads ##.banneritem_ad ##.bar_ad ##.barkerAd ##.base-ad-mpu ##.base_ad ##.base_printer_widgets_AdBreak ##.bb-adv-160x600 ##.bb-adv-300x250 ##.bbccom-advert ##.bbsTopAd ##.bcom_ad ##.bean-bag-ad ##.beauty_ads ##.before-comment-ad ##.belowNavAds ##.below_game_ad ##.below_player_ad ##.belowthread_advert ##.belowthread_advert_container ##.belt_ad ##.bet_AdBlock ##.between_page_ads ##.bex_ad ##.bg-ad-link ##.bg-ads ##.bgAdBlue ##.bgadgray10px ##.bgcolor_ad ##.bgnavad ##.big-ad ##.big-ads ##.big-box-ad ##.big-right-ad ##.bigAd ##.bigAdContainer ##.bigAdvBanner ##.bigBoxAdArea ##.bigCubeAd ##.big_ad ##.big_ads ##.big_center_ad ##.big_rectangle_page_ad ##.bigad ##.bigad1 ##.bigad2 ##.bigadleft ##.bigadright ##.bigads ##.bigadtxt1 ##.bigbox-ad ##.bigbox_ad ##.bigboxad ##.billboard-ad ##.billboard300x250 ##.billboardAd ##.billboard_ad ##.biz-ad ##.biz-ads ##.biz-adtext ##.biz-details-ad ##.bizCardAd ##.bizDetailAds ##.bkg-ad-browse ##.bl_adv_right ##.blacboard-ads-container ##.blk_advert ##.blocAdInfo ##.bloc_adsense_acc ##.block--ad-superleaderboard ##.block--ads ##.block--simpleads ##.block--views-premium-ad-slideshow-block ##.block-ad ##.block-ad-leaderboard ##.block-ad300 ##.block-ad_injector ##.block-ad_tag ##.block-admanager ##.block-ads ##.block-ads-bottom ##.block-ads-home ##.block-ads-top ##.block-ads1 ##.block-ads2 ##.block-ads3 ##.block-ads_top ##.block-adsense ##.block-adsense-managed ##.block-adsense_managed ##.block-adspace-full ##.block-advertisement ##.block-advertising ##.block-adzerk ##.block-altads ##.block-ami-ads ##.block-bf_ads ##.block-bg-advertisement ##.block-bg-advertisement-region-1 ##.block-boxes-ad ##.block-deca_advertising ##.block-dennis-adsense-afc ##.block-display-ads ##.block-doubleclick_ads ##.block-ec_ads ##.block-eg_adproxy ##.block-fan-ad ##.block-fc_ads ##.block-featured-sponsors ##.block-gc_ad ##.block-gg_ads ##.block-google-admanager ##.block-google-admanager-dfp ##.block-google_admanager ##.block-google_admanager2 ##.block-hcm-ads ##.block-hcm_ads ##.block-inner-adds ##.block-maniad ##.block-module-ad ##.block-module-ad-300x250 ##.block-module-ad-300x600 ##.block-nmadition ##.block-ohtdisplayad ##.block-openads ##.block-openadstream ##.block-openx ##.block-reklama ##.block-simpleads ##.block-skyscraper-ad ##.block-sn-ad-blog-wrapper ##.block-sponsor ##.block-sponsored-links ##.block-thirdage-ads ##.block-vh-adjuggler ##.block-wtg_adtech ##.block-zagat_ads ##.block1--ads ##.blockAd ##.blockAds ##.blockAdvertise ##.block_ad ##.block_ad_floating_bar ##.block_ad_sb_text ##.block_ad_sb_text2 ##.block_ad_sponsored_links ##.block_ad_sponsored_links-wrapper ##.block_ad_sponsored_links_localized ##.block_ad_sponsored_links_localized-wrapper ##.block_ads ##.block_adslot ##.block_adv ##.block_advert ##.blockad ##.blocked-ads ##.blockrightsmallads ##.blocsponsor ##.blog-ad ##.blog-ad-leader-inner ##.blog-ads ##.blog-ads-container ##.blog-ads-top ##.blog-advertisement ##.blog-view-ads ##.blog2AdIntegrated ##.blogAd ##.blogAdvertisement ##.blogArtAd ##.blogBigAd ##.blog_ad ##.blog_ad_continue ##.blog_divider_ad ##.blogads ##.blogads-sb-home ##.blogroll-ad-img ##.blogs_2_square_ad ##.blox3featuredAd ##.blue-ad ##.blxAdopsPlacement ##.bmg-sidebar-ads-125 ##.bmg-sidebar-ads-300 ##.bn_textads ##.bnr_ad ##.bodaciousad ##.body-ads ##.body-adzone ##.bodyAd ##.body_ad ##.body_sponsoredresults_bottom ##.body_sponsoredresults_middle ##.body_sponsoredresults_top ##.body_width_ad ##.bodyads ##.bodyads2 ##.bodybannerad ##.bodyrectanglead ##.bomAd ##.bonnier-ads ##.bonnier-ads-ad-bottom ##.bonnier-ads-ad-top ##.bookseller-header-advt ##.booster-ad ##.bostad ##.bot-728x90-ad ##.botAd ##.botRectAd ##.bot_ad ##.bot_ads ##.botad2 ##.bottom-ad ##.bottom-ad-box ##.bottom-ad-fr ##.bottom-ad-large ##.bottom-ad-placeholder ##.bottom-ad-wrapper ##.bottom-ad2 ##.bottom-ads ##.bottom-ads-wrapper ##.bottom-ads728 ##.bottom-banner-ad ##.bottom-center-adverts ##.bottom-game-ad ##.bottom-leaderboard-adslot ##.bottom-left-ad ##.bottom-right-advert ##.bottom-rightadvtsment ##.bottom-slider-ads ##.bottomAd ##.bottomAdBlock ##.bottomAds ##.bottomAdvTxt ##.bottomAdvert ##.bottomAdvertisement ##.bottomAdvt ##.bottomArticleAds ##.bottomBannerAd ##.bottomBannerAdsSmallBotLeftHolder ##.bottomELAd ##.bottomFriendsAds ##.bottomReviewAd ##.bottom_ad ##.bottom_ad_block ##.bottom_ad_placeholder ##.bottom_adbreak ##.bottom_ads ##.bottom_ads_wrapper_inner ##.bottom_adsense ##.bottom_advert_728x90 ##.bottom_advertise ##.bottom_banner_ad ##.bottom_banner_advert_text ##.bottom_bar_ads ##.bottom_right_ad ##.bottom_rightad ##.bottom_side_ad ##.bottom_sponsor ##.bottomad ##.bottomad-bg ##.bottomadarea ##.bottomads ##.bottomadtop ##.bottomadvert ##.bottomadwords ##.bottombarad ##.bottomleader ##.bottomleader-ad-wrapper ##.bottomrightrailAd ##.bottomvidad ##.box-ad ##.box-ad-a ##.box-ad-grey ##.box-ad-mr1 ##.box-ad-unit-j ##.box-ad-wsr ##.box-ads ##.box-ads-small ##.box-adsense ##.box-adv-300-home ##.box-adv-social ##.box-advert ##.box-advert-sponsored ##.box-advertisement ##.box-adverts ##.box-entry-ad-bottom-single ##.box-google-text-ad ##.box-radvert ##.box-recommend-ad ##.box-sidebar-ad ##.box-sidebar-ad-125 ##.box-sidebar-ad-160 ##.box-sidebar-ad-300 ##.boxAd ##.boxAdContainer ##.boxAdFields ##.boxAdMrec ##.boxAds ##.boxAdsInclude ##.boxAdvertisement ##.boxOuterAD ##.boxSponsor ##.box_ad ##.box_ad_container ##.box_ad_content ##.box_ad_horizontal ##.box_ad_spacer ##.box_ad_wrap ##.box_ads ##.box_ads728x90_holder ##.box_adv ##.box_adv1 ##.box_adv2 ##.box_adv_728 ##.box_adv_new ##.box_advertising ##.box_advertising_info ##.box_advertisment_62_border ##.box_content_ad ##.box_content_ads ##.box_publicidad ##.box_sidebar-ads ##.box_textads ##.box_title_ad ##.boxad ##.boxad120 ##.boxadcont ##.boxads ##.boxadv ##.boxcontentad ##.boxsponsor2 ##.boxyads ##.bps-ad-wrapper ##.bps-advertisement ##.bps-advertisement-inline-ads ##.bps-advertisement-placeholder ##.bps-search-chitika-ad ##.bq_ad_320x250 ##.bq_adleaderboard ##.bq_rightAd ##.br-ad ##.br-ad-text ##.br-banner-ad ##.br-right-rail-ad ##.branding-ad-gallery ##.branding-ad-wrapper ##.breadads ##.breakad_container ##.breakerAd ##.breakingNewsModuleSponsor ##.breakthrough-ad ##.broker-ad ##.broker-ads ##.broker-ads-center ##.brokerad ##.browse-ad-container ##.browse-banner_ad ##.browse-by-make-ad ##.browser_boot_ad ##.bs-ad ##.bsAdvert ##.bsa-in-post-ad-125-125 ##.bsa_ads ##.bsa_it_ad ##.bt_ad ##.btf-ad-medRect ##.btm_ad ##.btm_ad_container ##.btn-ad ##.btn-newad ##.btn_ad ##.budget_ads_1 ##.budget_ads_2 ##.budget_ads_3 ##.budget_ads_bg ##.bullet-sponsored-links ##.bullet-sponsored-links-gray ##.bunyad-ad ##.burstContentAdIndex ##.businessads ##.busrep_poll_and_ad_container ##.button-ad ##.button-ads ##.buttonAd ##.buttonAdSpot ##.buttonAds ##.button_ad ##.button_ads ##.button_advert ##.buttonad ##.buttonad_v2 ##.buttonadbox ##.buttonads ##.buySellAdsContainer ##.buysellAds ##.buysellAdsSmall ##.buzzAd ##.buzz_ad_block ##.buzz_ad_wrap ##.bx_ad ##.bx_ad_right ##.bxad ##.bz-ad ##.bzads-ic-ad-300-250-600 ##.c300x250-advert ##.c3_adverts ##.cA-adStack ##.cA-adStrap ##.cColumn-TextAdsBox ##.cLeftTextAdUnit ##.c_adsky ##.c_ligatus_nxn ##.calendarAd ##.calloutAd ##.can_ad_slug ##.canoeAdvertorial ##.carbonad ##.carbonad-tag ##.card--ad ##.cards-categorical-list-ad ##.care2_adspace ##.careerAdviceAd1 ##.carouselbanner_advert ##.cat_context_ad ##.catalog_ads ##.catalyst-ads ##.cate_right_ad ##.category-ad ##.category-advertorial ##.categorySponsorAd ##.category__big_game_container_body_games_advertising ##.categoryfirstad ##.categoryfirstadwrap ##.categorypage_ad1 ##.categorypage_ad2 ##.catfish_ad ##.cb-ad-banner ##.cb-ad-container ##.cb_ads ##.cb_navigation_ad ##.cbs-ad ##.cbs-ad-unit ##.cbs-ad-unit-wrapper ##.cbstv_ad_label ##.cbzadvert ##.cbzadvert_block ##.cc-advert ##.cdAdContainer ##.cdAdTitle ##.cdLanderAd ##.cdc-ad ##.cde_ads_right_top_300x250 ##.cdmainlineSearchAdParent ##.cdo-ad ##.cdo-ad-section ##.cdo-dicthomepage-btm-ad ##.cdsidebarSearchAdParent ##.center-ad ##.center-ad-banner ##.centerAd ##.centerAdBar ##.centerAds ##.center_ad ##.center_add ##.center_ads ##.center_adsense ##.centerad ##.centerads ##.centeradv ##.centered-ad ##.centered_wide_ad ##.cg_ad_slug ##.ch_advertisement ##.change-ad-h-btn ##.change_AdContainer ##.changeableadzone ##.channel-adv ##.chartad ##.chitika-ad ##.chitikaAdBlock ##.chitikaAdCopy ##.cinemabotad ##.clHeader_Ad ##.classifiedAdSplit ##.classifiedAdThree ##.clearerad ##.client-ad ##.close-ad-wrapper ##.close2play-ads ##.cm-ad ##.cm-ad-row ##.cm-hero-ad ##.cm-rp01-ad ##.cm-rp02-ad ##.cmAd ##.cmAdCentered ##.cmAdContainer ##.cmAdFind ##.cmAdSponsoredLinksBox ##.cmBottomAdRight ##.cmMediaRotatorAd ##.cmMediaRotatorAdSponsor ##.cmRecentOnAirAds ##.cmTeaseAdSponsoredLinks ##.cm_ads ##.cmam_responsive_ad_widget_class ##.cmg-ads ##.cms-Advert ##.cnAdContainer ##.cn_ad_placement ##.cnbcHeaderAd ##.cnbcRailAd ##.cnbc_badge_banner_ad_area ##.cnbc_banner_ad_area ##.cnbc_leaderboard_ad ##.cnn160AdFooter ##.cnnAd ##.cnnSearchSponsorBox ##.cnnStoreAd ##.cnnStoryElementBoxAd ##.cnnWCAdBox ##.cnnWireAdLtgBox ##.cnn_728adbin ##.cnn_adbygbin ##.cnn_adcntr300x100 ##.cnn_adcntr728x90 ##.cnn_adcntr728x90t ##.cnn_adspc300x100 ##.cnn_adspc336cntr ##.cnn_adtitle ##.cnn_fabcatad ##.cnn_grpnadclk ##.cnn_pt_ad ##.cnn_sectprtnrbox_cb ##.cnn_sectprtnrbox_grpn336 ##.cnt-half-page-ads ##.cnt-header-ad ##.cnt-right-box-ad ##.cnt-right-vertical-ad ##.cnt-right-vertical-ad-home ##.cnt_ad ##.cntrad ##.cobalt-ad ##.col-ad ##.col-line-ad ##.colRightAd ##.col_ad ##.col_header_ads_300x250 ##.column-ad ##.column2-ad ##.columnBoxAd ##.columnRightAdvert ##.column_3_ad ##.com-ad-server ##.comment-ad ##.comment-ad-wrap ##.comment-advertisement ##.comment_ad ##.comment_ad_box ##.commentsFavoritesAd ##.commentsbannerad ##.commercialAd ##.common-adv-box ##.common_advertisement_title ##.communityAd ##.comp_AdsFrontPage_300x600 ##.companion-ad ##.companion-ads ##.companionAd ##.companion_ad ##.compareBrokersAds ##.component-sponsored-links ##.conTSponsored ##.con_widget_advertising ##.conductor_ad ##.confirm_ad_left ##.confirm_ad_right ##.confirm_leader_ad ##.consoleAd ##.cont-ad ##.contads_middle ##.container-adds ##.container-adwords ##.container-rectangle-ad ##.container-top-adv ##.containerAdsense ##.containerSqAd ##.container_ad ##.container_row_ad ##.container_serendipity_plugin_google_adsense ##.contains-ad ##.content-ad ##.content-ad-outer-container ##.content-ad-side ##.content-ad-widget ##.content-ad-wrapper ##.content-advert ##.content-advertisment ##.content-box-inner-adsense ##.content-footer-ad ##.content-footer-ad-block ##.content-header-ad ##.content-item-ad-top ##.content-result-ads ##.content-unit-ad ##.contentAd ##.contentAd510 ##.contentAdBox ##.contentAdContainer ##.contentAdFoot ##.contentAdIndex ##.contentAds ##.contentAdsCommon ##.contentAdsWrapper ##.contentAdvertisement ##.contentTopAd ##.contentTopAdSmall ##.contentTopAds ##.content_468_ad ##.content_ad ##.content_ad_728 ##.content_ad_head ##.content_ads ##.content_ads_index ##.content_adsense ##.content_adsq ##.content_advert ##.content_advertising ##.content_bottom_adsense ##.content_column2_ad ##.content_middle_adv ##.content_tagsAdTech ##.contentad ##.contentad-home ##.contentad300x250 ##.contentad_right_col ##.contentadarticle ##.contentadfloatl ##.contentadleft ##.contentads1 ##.contentads2 ##.contentadstartpage ##.contentadstop1 ##.contentleftad ##.contentpage_searchad ##.contents-ads-bottom-left ##.contenttextad ##.contentwellad ##.contentwidgetads ##.contest_ad ##.context-ads ##.contextualAds ##.contextual_ad_unit ##.copy-adChoices ##.core-adplace ##.cornerBoxInnerWhiteAd ##.cornerad ##.cosmo-ads ##.cp-adsInited ##.cp_ad ##.cpaAdPosition ##.cpmstarHeadline ##.cpmstarText ##.cr_ad ##.cranky-ads-zone ##.create_ad ##.credited_ad ##.criAdv ##.cross_delete_ads ##.crumb-ad ##.cs-adv-wrapper ##.cs-mpu ##.csPromoAd ##.cscTextAd ##.cse_ads ##.csiAd_medium ##.cspAd ##.ct-ad-article ##.ct-ad-article-wrapper ##.ct-ads ##.ct-bottom-ads ##.ct_ad ##.ctn-advertising ##.ctnAdSkyscraper ##.ctnAdSquare300 ##.ctr-tss-ads ##.cube-ad ##.cubeAd ##.cube_ad ##.cube_ads ##.cubead-widget ##.currency_ad ##.custom-ad ##.custom-ad-container ##.custom-ads ##.custom-advert-banner ##.customAd ##.custom_ads ##.custom_banner_ad ##.custom_footer_ad ##.customadvert ##.customized_ad_module ##.cwAdvert ##.cwv2Ads ##.cxAdvertisement ##.cyads650x100 ##.da-custom-ad-box ##.darla_ad ##.dart-ad ##.dart-ad-content ##.dart-ad-grid ##.dart-ad-taboola ##.dart-ad-title ##.dart-advertisement ##.dart-leaderboard ##.dart-leaderboard-top ##.dart-medsquare ##.dartAd300 ##.dartAd491 ##.dartAdImage ##.dart_ad ##.dart_tag ##.dartad ##.dartadbanner ##.dartadvert ##.dartiframe ##.datafile-ad ##.dc-ad ##.dc-banner ##.dc-half-banner ##.dc-widget-adv-125 ##.dcAdvertHeader ##.deckAd ##.deckads ##.desktop-ad ##.desktop-aside-ad ##.desktop-aside-ad-hide ##.desktop-postcontentad-wrapper ##.desktop_ad ##.detail-ads ##.detailMpu ##.detailSidebar-adPanel ##.detail_ad ##.detail_article_ad ##.detail_top_advert ##.devil-ad-spot ##.dfad ##.dfad_first ##.dfad_last ##.dfad_pos_1 ##.dfad_pos_2 ##.dfad_pos_3 ##.dfad_pos_4 ##.dfad_pos_5 ##.dfad_pos_6 ##.dfads-javascript-load ##.dfp-ad ##.dfp-ad-advert_mpu_body_1 ##.dfp-ad-unit ##.dfp-ad-widget ##.dfp-banner ##.dfp-leaderboard ##.dfp-plugin-advert ##.dfp_ad ##.dfp_ad_caption ##.dfp_ad_content_bottom ##.dfp_ad_content_top ##.dfp_ad_footer ##.dfp_ad_header ##.dfrads ##.diggable-ad-sponsored ##.display-ad ##.display-ads-block ##.display-advertisement ##.displayAd ##.displayAd728x90Js ##.displayAdCode ##.displayAdSlot ##.displayAdUnit ##.displayAds ##.display_ad ##.div-google-adx ##.divAd ##.divAdright ##.divAdsBanner ##.divAdsLeft ##.divAdsRight ##.divAdvTopRight ##.divGoogleAdsTop ##.divReklama ##.divRepAd ##.divSponsoredBox ##.divSponsoredLinks ##.divTopADBanner ##.divTopADBannerWapper ##.div_adv300 ##.div_adv620 ##.div_adv728 ##.div_advertisement ##.div_advertorial ##.div_advstrip ##.div_banner468 ##.divad1 ##.divad2 ##.divad3 ##.divads ##.divadsensex ##.divider_ad ##.dlSponsoredLinks ##.dm-ads-125 ##.dm-ads-350 ##.dmRosMBAdBox ##.dmco_advert_iabrighttitle ##.dod_ad ##.double-ad ##.double-click-ad ##.double-square-ad ##.doubleGoogleTextAd ##.double_adsense ##.double_click_widget ##.doubleclick-ad ##.doubleclick_adtype ##.download-ad ##.downloadAds ##.download_ad ##.downloadad ##.drop-ad ##.dropdownAds ##.dsq_ad ##.dualAds ##.dwn_link_adv ##.dynamic-ad-wrap-b ##.dynamic-ads ##.dynamicLeadAd ##.dynamic_ad ##.dynamic_adslot ##.dynamicad1 ##.dynamicad2 ##.e-ad ##.eads ##.earAdv ##.east_ad_bg ##.east_ad_block ##.easy-ads ##.easyazon-block ##.eb_ad280 ##.ebayads ##.ec-ads ##.ec-ads-remove-if-empty ##.ec_ad_banner ##.ecosia-ads ##.editor_ad ##.editorial-adsense ##.editors-ads ##.ehs-adbridge ##.ej-advertisement-text ##.element-adplace ##.em-ad ##.em-ads-widget ##.em_ad_300x250 ##.em_ads_box_dynamic_remove ##.embAD ##.embed-ad ##.embeddedAd ##.embeddedAds ##.emm-ad ##.empty-ad ##.endemic_ads ##.engagement_ad ##.eniro_ad ##.enterpriseAd ##.entry-ad ##.entry-ads ##.entry-ads-110 ##.entry-body-ad ##.entry-bottom-ad ##.entry-injected-ad ##.entry-top-ad ##.entryAd ##.entry_sidebar_ads ##.entryad ##.eol-ads ##.epicgame-ads ##.esp_publicidad ##.et-single-post-ad ##.exec-advert-flash ##.expanding-ad ##.expertsAd ##.external-add ##.externalAdComponent ##.extrasColumnFuseAdLocal ##.ez-ad ##.ez-clientAd ##.ezAdsWidget ##.ezAdsense ##.ezoic-ad ##.fN-affiliateStrip ##.f_Ads ##.fbCalendarAds ##.fbPhotoSnowboxAds ##.fblockad ##.fc_splash_ad ##.fd-display-ad ##.feat_ads ##.featureAd ##.feature_ad ##.featured-ad ##.featured-ads ##.featured-sponsors ##.featuredAdBox ##.featuredAds ##.featuredBoxAD ##.featured_ad ##.featured_ad_item ##.featured_advertisers_box ##.featuredadvertising ##.feedBottomAd ##.fg_Ad ##.fi_adsense ##.finpostsads ##.fireplaceadleft ##.fireplaceadright ##.fireplaceadtop ##.first-ad ##.first_ad ##.firstad ##.firstpost_advert ##.firstpost_advert_container ##.fiveMinCompanionBanner ##.fixed-ad-160x600 ##.fixedAds ##.fixedRightAd ##.fl-adsense ##.flagads ##.flash-advertisement ##.flashAd ##.flash_ad ##.flash_advert ##.flashad ##.flashadd ##.flex-ad ##.flexAd ##.flexad ##.flexadvert ##.flexbanneritemad ##.flexiad ##.flipbook_v2_sponsor_ad ##.floatad ##.floatads ##.floated-ad ##.floated_right_ad ##.floating-advert ##.floatingAds ##.fm-badge-ad ##.fnadvert ##.fns_td_wrap ##.fold-ads ##.follower-ad-bottom ##.foot-ad ##.foot-ads ##.foot-advertisement ##.foot_adsense ##.footad ##.footer-300-ad ##.footer-ad ##.footer-ad-section ##.footer-ad-squares ##.footer-ads ##.footer-ads-wrapper ##.footer-adsbar ##.footer-adsense ##.footer-advert ##.footer-advert-large ##.footer-advertisement ##.footer-advertisements ##.footer-advertising-area ##.footer-banner-ad ##.footer-floating-ad ##.footer-leaderboard-ad ##.footer-text-ads ##.footerAd ##.footerAdModule ##.footerAdUnit ##.footerAdWrapper ##.footerAds ##.footerAdsWrap ##.footerAdslot ##.footerAdverts ##.footerFullAd ##.footerGoogleAdMainWarp ##.footerTextAd ##.footer_ad ##.footer_ad336 ##.footer_ads ##.footer_adv ##.footer_advertisement ##.footer_banner_ad_container ##.footer_block_ad ##.footer_bottom_ad ##.footer_bottomad ##.footer_line_ad ##.footer_text_ad ##.footer_text_adblog ##.footerad ##.footerads ##.footeradspace ##.footertextadbox ##.forex_ad_links ##.forum-ad-2 ##.forumAd ##.forum_ad_beneath ##.forumtopad ##.four-ads ##.four-six-eight-ad ##.four_button_threeone_ad ##.four_percent_ad ##.fp_ad_text ##.frame_adv ##.framead ##.freedownload_ads ##.freegame_bottomad ##.frn_adbox ##.frn_cont_adbox ##.frontads ##.frontpage-google-ad ##.frontpage-right-ad ##.frontpage-right-ad-hide ##.frontpage_ads ##.fs-ad-block ##.fs1-advertising ##.fs_ad_300x250 ##.ft-ad ##.ftdAdBar ##.ftdContentAd ##.ftr_ad ##.full-ad ##.full-width-ad ##.fullSizeAd ##.full_ad_box ##.full_ad_row ##.full_width_ad ##.fulladblock ##.fullbannerad ##.fusionAdLink ##.future_dfp-inline_ad ##.fw-mod-ad ##.fwAdTags ##.g-ad ##.g-ad-slot ##.g-ad-slot-toptop ##.g-adblock3 ##.g-advertisement-block ##.g2-adsense ##.g3-adsense ##.g3rtn-ad-site ##.gAdRows ##.gAdSky ##.gAds ##.gAds1 ##.gAdsBlock ##.gAdsContainer ##.gAdvertising ##.g_ad ##.g_ad336 ##.g_ads_200 ##.g_ads_728 ##.g_adv ##.g_ggl_ad ##.ga-ad-split ##.ga-ads ##.ga-textads-bottom ##.ga-textads-top ##.gaTeaserAds ##.gaTeaserAdsBox ##.gad_container ##.gads300x250 ##.gads_cb ##.gads_container ##.gadsense ##.gadstxtmcont2 ##.galleria-AdOverlay ##.gallery-ad ##.gallery-ad-holder ##.gallery-ad-wrapper ##.gallery-sidebar-ad ##.galleryAdvertPanel ##.galleryLeftAd ##.galleryRightAd ##.gallery_300x100_ad ##.gallery__aside-ad ##.gallery__footer-ad ##.gallery_ad ##.gallery_ads_box ##.galleryads ##.gam-300x250-default-ad-container ##.gam_ad_slot ##.game-ads ##.game-right-ad-container ##.gameAd ##.gameBottomAd ##.game__adv_containerLeaderboard ##.game_right_ad ##.game_under_ad ##.gamepage_boxad ##.gamepageadBox ##.gameplayads ##.games-ad-wrapper ##.games-ad300 ##.gamesPage_ad_container ##.gamesPage_ad_content ##.gamezebo_ad ##.gamezebo_ad_info ##.gbl_adstruct ##.gbl_advertisement ##.gdgt-header-advertisement ##.gdgt-postb-advertisement ##.geeky_ad ##.gels-inlinead ##.gen_side_ad ##.general-adzone ##.generic-ad-module ##.generic-ad-title ##.generic_300x250_ad ##.geoAd ##.getridofAds ##.getridofAdsBlock ##.gfp-banner ##.ggads ##.ggadunit ##.ggadwrp ##.gglAds ##.gglads300 ##.gl_ad ##.glamsquaread ##.glance_banner_ad ##.globalAd ##.globalAdLargeRect ##.globalAdLeaderBoard ##.global_banner_ad ##.gm-ad-lrec ##.gn_ads ##.go-ad ##.go-ads-widget-ads-wrap ##.goog_ad ##.googad ##.googads ##.google-ad ##.google-ad-728-90 ##.google-ad-block ##.google-ad-container ##.google-ad-content ##.google-ad-image ##.google-ad-side_ad ##.google-ad-square-sidebar ##.google-ad-widget ##.google-ads ##.google-ads-boxout ##.google-ads-group ##.google-ads-leaderboard ##.google-ads-long ##.google-ads-obj ##.google-ads-responsive ##.google-ads-right ##.google-ads-rodape ##.google-ads-sidebar ##.google-ads-slim ##.google-ads-widget ##.google-ads-wrapper ##.google-ads2 ##.google-adsbygoogle ##.google-adsense ##.google-afc-wrapper ##.google-csi-ads ##.google-entrepreneurs-ad ##.google-right-ad ##.google-sponsored ##.google-sponsored-ads ##.google-sponsored-link ##.google-sponsored-links ##.google-text-ads ##.google-user-ad ##.google300x250 ##.google300x250BoxFooter ##.google300x250TextDetailMiddle ##.google300x250TextFooter ##.google468 ##.google468_60 ##.google728x90 ##.google728x90TextDetailTop ##.googleAd ##.googleAd-content ##.googleAd-list ##.googleAd300x250 ##.googleAd300x250_wrapper ##.googleAdBox ##.googleAdContainer ##.googleAdContainerSingle ##.googleAdFoot ##.googleAdSearch ##.googleAdSense ##.googleAdSenseModule ##.googleAdTopTipDetails ##.googleAdWrapper ##.googleAd_160x600 ##.googleAd_1x1 ##.googleAd_728x90 ##.googleAd_body ##.googleAdd ##.googleAds ##.googleAds336 ##.googleAds728 ##.googleAds_article_page_above_comments ##.googleAdsense ##.googleAdsense468x60 ##.googleAdv1 ##.googleBannerWrapper ##.googleContentAds ##.googleInsideAd ##.googleLgRect ##.googleProfileAd ##.googleSearchAd_content ##.googleSearchAd_sidebar ##.googleSideAd ##.googleSkyWrapper ##.googleSubjectAd ##.google_728x90 ##.google_ad ##.google_ad3 ##.google_ad336 ##.google_ad_bg ##.google_ad_btn ##.google_ad_container ##.google_ad_label ##.google_ad_mrec ##.google_ad_right ##.google_ad_wide ##.google_add ##.google_add_container ##.google_admanager ##.google_ads ##.google_ads_468x60 ##.google_ads_bom_block ##.google_ads_bom_title ##.google_ads_content ##.google_ads_header11 ##.google_ads_sidebar ##.google_ads_v3 ##.google_adsense ##.google_adsense1 ##.google_adsense1_footer ##.google_adsense_footer ##.google_adsense_sidebar_left ##.google_afc ##.google_afc_ad ##.google_afc_categorymain ##.google_top_adsense ##.google_top_adsense1 ##.google_top_adsense1_footer ##.google_top_adsense_footer ##.google_txt_ads_mid_big_img ##.googlead ##.googlead-sidebar ##.googleadArea ##.googlead_idx_b_97090 ##.googlead_idx_h_97090 ##.googlead_iframe ##.googlead_outside ##.googleadbottom ##.googleadcontainer ##.googleaddiv ##.googleaddiv2 ##.googleadiframe ##.googleads ##.googleads-bottommiddle ##.googleads-container ##.googleads-topmiddle ##.googleads_300x250 ##.googleads_title ##.googleadsense ##.googleadsrectangle ##.googleadvertisemen120x600 ##.googleadvertisement ##.googleadwrap ##.googleafc ##.googlebanwide ##.googleimagead1 ##.googleimagead2 ##.googlepostads ##.googley_ads ##.gpAdBox ##.gpAdFooter ##.gpAds ##.gp_adbanner--bottom ##.gp_adbanner--top ##.gpadvert ##.gpt-ad ##.gpt-ads ##.gr-adcast ##.gradientAd ##.graphic_ad ##.grev-ad ##.grey-ad-line ##.grey-ad-notice ##.greyAd ##.greyad ##.grid-ad ##.grid-advertisement ##.grid-item-ad ##.gridAd ##.gridAdRow ##.gridSideAd ##.gridstream_ad ##.group-google-ads ##.group_ad ##.grv_is_sponsored ##.gsAd ##.gsfAd ##.gsl-ads ##.gt_ad ##.gt_ad_300x250 ##.gt_ad_728x90 ##.gt_adlabel ##.gtadlb ##.gtop_ad ##.gujAd ##.gutter-ad-left ##.gutter-ad-right ##.gutter-ad-wrapper ##.gutterAdHorizontal ##.gx_ad ##.h-ad ##.h-ad-728x90-bottom ##.h-ad-remove ##.h-ads ##.h-large-ad-box ##.h-top-ad ##.h11-ad-top ##.h_Ads ##.h_ad ##.half-ad ##.halfPageAd ##.half_ad_box ##.halfpage_ad_container ##.has-ad ##.hbPostAd ##.hbox_top_sponsor ##.hcf-ad ##.hcf-ad-rectangle ##.hcf-cms-ad ##.hd-adv ##.hdTopAdContainer ##.hd_advert ##.hd_below_player_ad ##.hdr-ad ##.hdr-ad-text ##.hdr-ads ##.hdrAd ##.hdr_ad ##.head-ads ##.headAd ##.head_ad ##.head_ad_wrapper ##.head_ads ##.head_adv ##.head_advert ##.headad ##.headadcontainer ##.header--ad-space ##.header-ad ##.header-ad-banner ##.header-ad-new-wrap ##.header-ad-space ##.header-ad-wrap ##.header-ad-wrapper ##.header-ad234x60left ##.header-ad234x60right ##.header-adplace ##.header-ads ##.header-ads-holder ##.header-adsense ##.header-adv ##.header-advert ##.header-advert-container ##.header-banner-ads ##.header-bannerad ##.header-google-ads ##.header-sponsor ##.header-taxonomy-image-sponsor ##.header-top-ad ##.header15-ad ##.header3-advert ##.header728-ad ##.headerAd ##.headerAd1 ##.headerAdArea ##.headerAdCode ##.headerAdWrapper ##.headerAds ##.headerAdspace ##.headerAdvert ##.headerTextAd ##.headerTopAds ##.header_ad ##.header_ad_2 ##.header_ad_center ##.header_ad_div ##.header_ads ##.header_ads_promotional ##.header_adsense_banner ##.header_advert ##.header_advertisement ##.header_advertisement_text ##.header_advertisment ##.header_classified_ads ##.header_leaderboard_ad ##.header_right_ad ##.headerad ##.headerad-720 ##.headerad-placeholder ##.headeradarea ##.headeradhome ##.headeradinfo ##.headeradright ##.headerads ##.heading-ad-space ##.heatmapthemead_ad_widget ##.hero-ad ##.hi5-ad ##.hidden-ad ##.hideAdMessage ##.hidePauseAdZone ##.hide_ad ##.highlights-ad ##.highlightsAd ##.hl-post-center-ad ##.hm_advertisment ##.hm_top_right_google_ads ##.hm_top_right_google_ads_budget ##.hn-ads ##.home-300x250-ad ##.home-ad ##.home-ad-container ##.home-ad-links ##.home-ad728 ##.home-ads ##.home-ads-container ##.home-ads-container1 ##.home-advert ##.home-area3-adv-text ##.home-body-ads ##.home-features-ad ##.home-sidebar-ad-300 ##.home-slider-ads ##.home-sticky-ad ##.home-top-of-page__top-box-ad ##.home-top-right-ads ##.homeAd ##.homeAd1 ##.homeAd2 ##.homeAdBox ##.homeAdBoxA ##.homeAdBoxBetweenBlocks ##.homeAdBoxInBignews ##.homeAdFullBlock ##.homeAdSection ##.homeAddTopText ##.homeCentreAd ##.homeMainAd ##.homeMediumAdGroup ##.homePageAds ##.homeSubAd ##.homeTextAds ##.home_ad ##.home_ad_300x100 ##.home_ad_300x250 ##.home_ad_bottom ##.home_ad_large ##.home_adblock ##.home_advert ##.home_advertisement ##.home_advertorial ##.home_box_latest_ads ##.home_mrec_ad ##.home_offer_adv ##.home_sidebar_ads ##.home_sway_adv ##.home_top_right_ad ##.home_top_right_ad_label ##.homead ##.homeadnews ##.homefront468Ad ##.homepage-300-250-ad ##.homepage-ad ##.homepage-ad-block-padding ##.homepage-ad-buzz-col ##.homepage-advertisement ##.homepage-footer-ad ##.homepage-footer-ads ##.homepage-right-rail-ad ##.homepage-sponsoredlinks-container ##.homepage300ad ##.homepageAd ##.homepageFlexAdOuter ##.homepageMPU ##.homepage__ad ##.homepage__ad--middle-leader-board ##.homepage__ad--top-leader-board ##.homepage__ad--top-mrec ##.homepage_ads ##.homepage_block_ad ##.homepage_middle_right_ad ##.homepageinline_adverts ##.homestream-ad ##.hor_ad ##.hori-play-page-adver ##.horisont_ads ##.horiz_adspace ##.horizontal-ad-holder ##.horizontalAd ##.horizontalAdText ##.horizontalAdvert ##.horizontal_ad ##.horizontal_adblock ##.horizontal_ads ##.horizontalbtad ##.horizontaltextadbox ##.horizsponsoredlinks ##.hortad ##.house-ad ##.house-ads ##.houseAd ##.houseAd1 ##.houseAdsStyle ##.housead ##.hover_300ad ##.hover_ads ##.hoverad ##.hp-col4-ads ##.hp-content__ad ##.hp-inline-ss-service-ad ##.hp-main__rail__footer__ad ##.hp-slideshow-right-ad ##.hp-ss-service-ad ##.hp2-adtag ##.hpPollQuestionSponsor ##.hpPriceBoardSponsor ##.hp_320-250-ad ##.hp_ad_300 ##.hp_ad_box ##.hp_ad_cont ##.hp_ad_text ##.hp_horizontal_ad ##.hp_t_ad ##.hp_w_ad ##.hpa-ad1 ##.hr-ads ##.hr_ad ##.hss-ad ##.hss-ad-300x250_1 ##.hss_static_ad ##.hst-contextualads ##.ht_ad_widget ##.html-advertisement ##.html-component-ad-filler ##.html5-ad-progress-list ##.hyad ##.hype_adrotate_widget ##.i360ad ##.i_ad ##.ib-adv ##.ib-figure-ad ##.ibm_ad_bottom ##.ibm_ad_text ##.ibt-top-ad ##.ic-ads ##.ico-adv ##.icon-advertise ##.iconAdChoices ##.icon_ad_choices ##.idGoogleAdsense ##.idMultiAd ##.idc-adContainer ##.idc-adWrapper ##.idgGoogleAdTag ##.iframe-ad ##.iframe-ads ##.iframeAd ##.iframead ##.iframeadflat ##.im-topAds ##.image-ad-336 ##.image-advertisement ##.image-viewer-ad ##.image-viewer-mpu ##.imageAd ##.imageAdBoxTitle ##.imageads ##.imagetable_ad ##.img_ad ##.img_ads ##.imgad ##.imgur-ad ##.imuBox ##.in-ad ##.in-between-ad ##.in-node-ad-300x250 ##.in-page-ad ##.in-story-ads ##.in-story-text-ad ##.inArticleAdInner ##.inPageAd ##.inStoryAd-news2 ##.in_article_ad ##.in_content_ad_container ##.in_up_ad_game ##.indEntrySquareAd ##.indent-advertisement ##.index-adv ##.index-after-second-post-ad ##.index_728_ad ##.index_ad ##.index_right_ad ##.indexad ##.indie-sidead ##.indy_googleads ##.info-ads ##.info-advert-160x600 ##.info-advert-300x250 ##.info-advert-728x90 ##.info-advert-728x90-inside ##.infoBoxThreadPageRankAds ##.ingameadbox ##.ingameboxad ##.ingridAd ##.inhouseAdUnit ##.inhousead ##.injectedAd ##.inline-ad ##.inline-ad-wrap ##.inline-ad-wrapper ##.inline-adblock ##.inline-mpu ##.inline-mpu-left ##.inlineAd ##.inlineAdContainer ##.inlineAdImage ##.inlineAdInner ##.inlineAdNotice ##.inlineAdText ##.inlineAdTour ##.inlineAd_content ##.inlineAdvert ##.inlineAdvertisement ##.inlineSideAd ##.inline_ad ##.inline_ad_container ##.inline_ad_title ##.inline_ads ##.inlinead ##.inlinead-tagtop ##.inlineadsense ##.inlineadtitle ##.inlist-ad ##.inlistAd ##.inner-ad ##.inner-advt-banner-3 ##.inner468ad ##.innerAds ##.innerContentAd ##.inner_ad ##.inner_ad_advertise ##.inner_big_ad ##.innerad ##.innerpostadspace ##.inpostad ##.insert-advert-ver01 ##.insert-post-ads ##.insertAd_AdSlice ##.insertAd_Rectangle ##.insertAd_TextAdBreak ##.insert_ad ##.insert_advertisement ##.insertad ##.insideStoryAd ##.inside_ad ##.inside_ad_box ##.instructionAdvHeadline ##.insurance-ad ##.intad ##.inteliusAd_image ##.interest-based-ad ##.internal-ad ##.internalAdSection ##.internalAdsContainer ##.internal_ad ##.interstitial-ad ##.interstitial-ad600 ##.interstitial468x60 ##.interstitial_ad_wrapper ##.ion-ad ##.ione-widget-dart-ad ##.ipm-sidebar-ad-middle ##.iprom-ad ##.ipsAd ##.iqadlinebottom ##.is-sponsored ##.is24-adplace ##.isAd ##.is_trackable_ad ##.isad_box ##.island-ad ##.islandAd ##.islandAdvert ##.island_ad ##.islandad ##.isocket_ad_row ##.item-ad ##.item-ad-leaderboard ##.item-ads ##.item-advertising ##.item-container-ad ##.item-housead ##.item-housead-last ##.itemAdvertise ##.item_ads ##.ja-ads ##.jalbum-ad-container ##.jam-ad ##.jimdoAdDisclaimer ##.jobkeywordads ##.jobs-ad-box ##.jobs-ad-marker ##.joead728 ##.jp-advertisment-promotional ##.js-ad-home ##.js-ad-wrapper ##.js-advert ##.js-advert--vc ##.js-header-ad ##.js-stream-featured-ad ##.jsx-adcontainer ##.juicyads_300x250 ##.jumboAd ##.kd_ads_block ##.kdads-empty ##.kdads-link ##.keyword-ads-block ##.kip-banner-ad ##.knowledgehub_ad ##.kw_advert ##.kw_advert_pair ##.l-ad-300 ##.l-ad-728 ##.l-adsense ##.l-bottom-ads ##.l-header-advertising ##.l300x250ad ##.l_ad_sub ##.label-ad ##.labelads ##.labeled_ad ##.landing-page-ads ##.landingAdRail ##.landing_adbanner ##.large-btn-ad ##.large-right-ad ##.largeAd ##.largeRecAdNewsContainerRight ##.largeRectangleAd ##.largeUnitAd ##.large_ad ##.large_add_container ##.largesideadpane ##.lastAdvertorial ##.lastRowAd ##.lastads ##.lastpost_advert ##.layer_text_ad ##.layeradinfo ##.layout_communityad_right_ads ##.lazyad ##.lazyload_ad ##.lazyload_ad_article ##.lb-ad ##.lbc-ad ##.lcontentbox_ad ##.lead-ad ##.lead-ads ##.leadAd ##.leader-ad ##.leaderAd ##.leaderAdSlot ##.leaderAdTop ##.leaderAdvert ##.leaderBoardAdHolder ##.leaderBoardAdvert ##.leaderOverallAdArea ##.leader_ad ##.leader_aol ##.leaderboard-ad ##.leaderboard-ad-container ##.leaderboard-ad-green ##.leaderboard-ad-grid ##.leaderboard-ad-inner ##.leaderboard-ad-main ##.leaderboard-adblock ##.leaderboard-ads ##.leaderboard-advert ##.leaderboard-advertisement ##.leaderboardAd ##.leaderboardAdContainer ##.leaderboardAdContainerInner ##.leaderboardFooter_ad ##.leaderboard_ad ##.leaderboard_ad_unit ##.leaderboard_ad_unit_groups ##.leaderboard_adv ##.leaderboard_banner_ad ##.leaderboardad ##.leaderboardadmiddle ##.leaderboardadtop ##.leaderboardadwrap ##.left-ad ##.left-ad180 ##.left-ads ##.left-advert ##.left-column-rectangular-ad ##.left-column-virtical-ad ##.left-rail-ad ##.left-rail-horizontal-ads ##.left-sidebar-box-ads ##.left-takeover-ad ##.left-takeover-ad-sticky ##.left120X600AdHeaderText ##.leftAd ##.leftAdColumn ##.leftAdContainer ##.leftAd_bottom_fmt ##.leftAd_top_fmt ##.leftAds ##.leftAdvert ##.leftCol_advert ##.leftColumnAd ##.left_300_ad ##.left_ad ##.left_ad_160 ##.left_ad_areas ##.left_ad_box ##.left_ad_container ##.left_adlink ##.left_ads ##.left_adsense ##.left_advertisement_block ##.left_col_ad ##.left_google_add ##.left_sidebar_wide_ad ##.leftad ##.leftadd ##.leftadtag ##.leftbar_ad_160_600 ##.leftbarads ##.leftbottomads ##.leftnavad ##.leftrighttopad ##.leftsidebar_ad ##.lefttopad1 ##.legacy-ads ##.legal-ad-choice-icon ##.lgRecAd ##.lg_ad ##.liboxads ##.ligatus ##.lightad ##.lijit-ad ##.linead ##.linkAD ##.link_adslider ##.link_advertise ##.linkads ##.linkedin-sponsor ##.links_google_adx ##.list-ad ##.list-ads ##.listAdvertGenerator ##.listad ##.listing-content-ad-container ##.listing-item-ad ##.listingAd ##.listings-bottom-ad-w ##.listings_ad ##.little_vid_ads ##.live-search-list-ad-container ##.live_tv_sponsorship_ad ##.liveads ##.livingsocial-ad ##.ljad ##.llsAdContainer ##.lnad ##.loadadlater ##.local-ads ##.localad ##.location-ad ##.log_ads ##.logo-ad ##.logoAd-hanging ##.logoAds ##.logo_AdChoices ##.logoad ##.logoutAd ##.logoutAdContainer ##.longAd ##.longAdBox ##.longAds ##.longBannerAd ##.long_ad ##.longform-ad ##.loop-ad ##.loop_google_ad ##.lottery-ad-container ##.lower-ads ##.lowerAd ##.lowerAds ##.lowerContentBannerAd ##.lowerContentBannerAdInner ##.lower_ad ##.lpt_adsense_bottom_content ##.lqm-ads ##.lqm_ad ##.lr-ad ##.lr_skyad ##.lsn-yahooAdBlock ##.lt_ad_call ##.luma-ad ##.luxeAd ##.m-ad ##.m-ad-tvguide-box ##.m-advertisement ##.m-advertisement--container ##.m-layout-advertisement ##.m-mem--ad ##.m-sponsored ##.m4-adsbygoogle ##.mTopAd ##.m_ad300 ##.m_banner_ads ##.macAd ##.macad ##.mad_adcontainer ##.madison_ad ##.magad ##.magazine_box_ad ##.main-ad ##.main-ads ##.main-advert ##.main-column-ad ##.main-footer-ad ##.main-right-ads ##.main-tabs-ad-block ##.mainAd ##.mainAdContainer ##.mainAds ##.mainEcoAd ##.mainLeftAd ##.mainLinkAd ##.mainRightAd ##.main_ad ##.main_ad_adzone_5_ad_0 ##.main_ad_adzone_6_ad_0 ##.main_ad_adzone_7_ad_0 ##.main_ad_adzone_7_ad_1 ##.main_ad_adzone_8_ad_0 ##.main_ad_adzone_8_ad_1 ##.main_ad_adzone_9_ad_0 ##.main_ad_adzone_9_ad_1 ##.main_ad_bg ##.main_ad_bg_div ##.main_ad_container ##.main_adbox ##.main_ads ##.main_adv ##.main_intro_ad ##.main_right_ad ##.main_wrapper_upper_ad_area ##.mainadWrapper ##.mainadbox ##.mantis-ad ##.manual-ad ##.mapAdvertising ##.map_google_ad ##.map_media_banner_ad ##.mapped-ad ##.marginadsthin ##.market-ad ##.market-ad-small ##.marketing-ad ##.marketplace-ad ##.marketplaceAd ##.marketplaceAdShell ##.markplace-ads ##.marquee-ad ##.master_post_advert ##.masthead-ad ##.masthead-ad-control ##.masthead-ads ##.mastheadAds ##.masthead_ad_banner ##.masthead_ads_new ##.masthead_topad ##.matador_sidebar_ad_600 ##.mb-list-ad ##.mcx-content-ad ##.md-adv ##.mdl-ad ##.mdl-quigo ##.medColModAd ##.medRecContainer ##.medRect ##.med_ad_box ##.media--ad ##.media-ad-rect ##.media-advert ##.mediaAd ##.mediaAdContainer ##.mediaResult_sponsoredSearch ##.media_ad ##.medium-rectangle-ad ##.medium-rectangle-advertisement ##.mediumRectangleAd ##.mediumRectangleAdvert ##.medium_ad ##.medium_rectangle_ad_container ##.mediumad ##.medo-ad-section ##.medo-ad-wideskyscraper ##.medrect-ad ##.medrect-ad2 ##.medrectAd ##.medrect_ad ##.medrectadv4 ##.member-ads ##.memberAdsContainer ##.member_ad_banner ##.meme_adwrap ##.memrise_ad ##.menu-ad ##.menuAd ##.menuAds-cage ##.menuItemBannerAd ##.menuad ##.menueadimg ##.merchantAdsBoxColRight ##.messageBoardAd ##.message_ads ##.metaRedirectWrapperBottomAds ##.metaRedirectWrapperTopAds ##.meta_ad ##.metaboxType-sponsor ##.mf-ad300-container ##.mgid-wrapper ##.micro_ad ##.mid-ad-wrapper ##.mid-advert ##.mid_4_ads ##.mid_ad ##.mid_article_ad_label ##.mid_banner_ad ##.mid_page_ad ##.mid_page_ad_big ##.mid_right_ads ##.midad ##.middle-ad ##.middle-ads728 ##.middle-footer-ad ##.middleAd ##.middleAdLeft ##.middleAdMid ##.middleAdRight ##.middleAds ##.middle_AD ##.middle_ad ##.middle_ads ##.middlead ##.middleadouter ##.midpost-ad ##.min_navi_ad ##.mini-ad ##.miniHeaderAd ##.mini_ads ##.mini_ads_bottom ##.mini_ads_right ##.miniad ##.miniads ##.misc-ad ##.misc-ad-label ##.miscAd ##.ml-adverts-sidebar-1 ##.ml-adverts-sidebar-2 ##.ml-adverts-sidebar-4 ##.ml-adverts-sidebar-bottom-1 ##.ml-adverts-sidebar-bottom-2 ##.ml-adverts-sidebar-bottom-3 ##.ml-adverts-sidebar-random ##.mlaAd ##.mm-ad-mpu ##.mm-ad-sponsored ##.mmc-ad ##.mmc-ad-wrap-2 ##.mmcAd_Iframe ##.mnopolarisAd ##.mo_googlead ##.mobile-ad ##.mobileAdWrap ##.mobileAdvertInStreamHighlightText ##.mobileAppAd ##.mobile_ad_container ##.mobile_featuredad ##.mobile_featuredad_article ##.mod-ad ##.mod-ad-1 ##.mod-ad-2 ##.mod-ad-box ##.mod-ad-lrec ##.mod-ad-n ##.mod-adblock ##.mod-adcpc ##.mod-adopenx ##.mod-ads ##.mod-google-ads ##.mod-horizontal-ad ##.mod-sponsored-links ##.mod-trbad ##.mod-tss-ads-wrapper ##.mod-vertical-ad ##.mod_ad ##.mod_ad_imu ##.mod_ad_top ##.mod_admodule ##.mod_ads ##.mod_openads ##.modal-ad ##.module-ad ##.module-ad-small ##.module-ads ##.module-advert ##.module-advertisement ##.module-image-ad ##.module-rectangleads ##.module-sponsored-ads ##.moduleAd ##.moduleAdSpot ##.moduleAdvert ##.moduleAdvertContent ##.moduleBannerAd ##.module_ad ##.module_ad_disclaimer ##.module_box_ad ##.module_header_sponsored ##.modulegad ##.moduletable-adsponsor ##.moduletable-advert ##.moduletable-bannerAd6 ##.moduletable-centerad ##.moduletable-googleads ##.moduletable-rectangleads ##.moduletable_ad-right ##.moduletable_ad160x600_center ##.moduletable_ad300x250 ##.moduletable_adtop ##.moduletable_advertisement ##.moduletable_top_ad ##.moduletableadvert ##.moduletableexclusive-ads ##.moduletablesquaread ##.moduletabletowerad ##.mom-ad ##.moneyball-ad ##.monsterad ##.moreAdBlock ##.mos-ad ##.mosaicAd ##.mostpop_sponsored_ad ##.motherboard-ad ##.mp-ad ##.mpu-ad ##.mpu-ad-con ##.mpu-ad-top ##.mpu-advert ##.mpu-c ##.mpu-container-blank ##.mpu-footer ##.mpu-fp ##.mpu-holder ##.mpu-leaderboard ##.mpu-left ##.mpu-mediatv ##.mpu-right ##.mpu-title ##.mpu-top-left ##.mpu-top-left-banner ##.mpu-top-right ##.mpu-unit ##.mpu-wrapper ##.mpu01 ##.mpu250 ##.mpu600 ##.mpuAd ##.mpuAdArea ##.mpuAdSlot ##.mpuAdvert ##.mpuArea ##.mpuBox ##.mpuContainer ##.mpuMiddle ##.mpuTextAd ##.mpu_Ad ##.mpu_ad ##.mpu_advert ##.mpu_advertisement_border ##.mpu_container ##.mpu_gold ##.mpu_holder ##.mpu_placeholder ##.mpu_platinum ##.mpu_side ##.mpu_text_ad ##.mpuad ##.mpuads ##.mpuholderportalpage ##.mrec_advert ##.ms-ad-superbanner ##.ms-ads-link ##.ms_header_ad ##.msat-adspace ##.msfg-shopping-mpu ##.msnChannelAd ##.msn_ad_wrapper ##.mt-ad-container ##.mt-header-ads ##.mtv-adChoicesLogo ##.mtv-adv ##.multiadwrapper ##.mvAd ##.mvAdHdr ##.mvp_block_type_ad_module ##.mvw_onPageAd1 ##.mwaads ##.mxl_ad_inText_250 ##.my-ad250x300 ##.my-ads ##.myAds ##.myAdsGroup ##.mypicadsarea ##.myplate_ad ##.nSponsoredLcContent ##.nSponsoredLcTopic ##.n_ad ##.naMediaAd ##.nadvt300 ##.narrow_ad_unit ##.narrow_ads ##.native-ad ##.native-ad-link ##.native-ad-promoted-provider ##.nature-ad ##.nav-ad ##.nav-adWrapper ##.navAdsBanner ##.navBads ##.nav_ad ##.nav_textads ##.navad ##.navadbox ##.navcommercial ##.navi_ad300 ##.naviad ##.nba300Ad ##.nba728Ad ##.nbaAdNotice ##.nbaAroundAd2 ##.nbaT3Ad160 ##.nbaTVPodAd ##.nbaTextAds ##.nbaTwo130Ads ##.nbc_ad_carousel_wrp ##.ndmadkit ##.netPost_ad1 ##.netPost_ad3 ##.netads ##.netshelter-ad ##.network-ad-two ##.new-ad-box ##.new-ads-scroller ##.newHeaderAd ##.newPex_forumads ##.newTopAdContainer ##.new_ad1 ##.newad ##.newad1 ##.newadsky-wrapper ##.news-ad ##.news-place-ad-info ##.newsAd ##.news_ad_box ##.news_article_ad_google ##.news_footer_ad_container ##.newsblock-ads ##.newsletter_ad ##.newsstackedAds ##.newstream_ad ##.newsviewAdBoxInNews ##.newsvinemsn_adtype ##.nexusad ##.nf-adbox ##.ninemsn-footer-ad ##.ninth-box-ad ##.nn-mpu ##.no1postadvert ##.noAdForLead ##.noTitleAdBox ##.node-ad ##.node-content-ad ##.node_ad_wrapper ##.nomobilead ##.nonsponserIABAdBottom ##.normalAds ##.normalad ##.northad ##.not-an-ad-header ##.note-advertisement ##.npAdGoogle ##.npSponsorTextAd ##.nrAds ##.nr_partners ##.nrelate .nr_partner ##.nsAdRow ##.nscr300Ad ##.nscrMidAdBlock ##.nscrT1AdBlock ##.ntnlad ##.nu2ad ##.nuffnangad ##.nw-ad ##.nw-ad-468x60 ##.nw-ad-label ##.nzs-ads ##.oad-ad ##.oas-ad ##.oas-bottom-ads ##.oas-leaderboard-ads ##.oasInAds ##.oas_ad ##.oas_add ##.oas_advertisement ##.oas_sidebar_v7 ##.oasad ##.oasads ##.ob_ads_header ##.ob_container .item-container-obpd ##.ob_dual_right > .ob_ads_header ~ .odb_div ##.oba_message ##.ocp-sponsor ##.odc-nav-ad ##.ody-sponsor ##.offer_sponsoredlinks ##.oi_horz_ad_container ##.oio-banner-zone ##.oio-link-sidebar ##.oio-openslots ##.oio-zone-position ##.old-advertorial-block ##.omnitureAdImpression ##.on-demand-ad ##.on_single_ad_box ##.one-ad ##.oneColumnAd ##.onethirdadholder ##.opaAd ##.openads ##.openadstext_after ##.openx ##.openx-ad ##.openx_10 ##.openx_11 ##.openx_15 ##.openx_16 ##.openx_17 ##.openx_3 ##.openx_4 ##.openx_ad ##.openx_frame ##.openxbuttons ##.optional-ad ##.os-advertisement ##.osan-ads ##.other-posts-ads ##.other_adv2 ##.otj_adspot ##.outbrain_ad_li ##.outbrain_dual_ad_whats_class ##.outbrain_ul_ad_top ##.outer-ad-container ##.outerAd_300x250_1 ##.outermainadtd1 ##.outgameadbox ##.outside_ad ##.ovAdLabel ##.ovAdPromo ##.ovAdSky ##.ovAdartikel ##.ov_spns ##.ovadsenselabel ##.overflow-ad ##.overlay-ad-container ##.overlay_ad ##.ox-holder ##.ox_ad ##.ozadtop ##.ozadtop3 ##.p2_right_ad ##.p75_sidebar_ads ##.p_topad ##.pa_ads_label ##.paddingBotAd ##.pads2 ##.padvertlabel ##.page-ad ##.page-ad-container ##.page-advert ##.page-pencil-ad-container-bottom ##.pageAds ##.pageBottomGoogleAd ##.pageGoogleAd ##.pageGoogleAdFlat ##.pageGoogleAdSubcontent ##.pageGoogleAds ##.pageGoogleAdsContainer ##.pageLeaderAd ##.pageSkinAds ##.page_ad ##.page_content_right_ad ##.pagead ##.pagebuilder_ad ##.pageclwideadv ##.pagenavindexcontentad ##.pair_ads ##.pane-ad-block ##.pane-ad-manager-bottom-right-rail-circ ##.pane-ad-manager-middle ##.pane-ad-manager-middle1 ##.pane-ad-manager-right ##.pane-ad-manager-right1 ##.pane-ad-manager-right2 ##.pane-ad-manager-right3 ##.pane-ad-manager-shot-business-circ ##.pane-ad-manager-subscribe-now ##.pane-ads ##.pane-frontpage-ad-banner ##.pane-frontpage-ad-banner-hk ##.pane-openx ##.pane-site-ads ##.pane-sponsored-links ##.pane-textlinkads-26 ##.pane-tw-ad-master-ad-300x250a ##.pane-tw-ad-master-ad-300x600 ##.pane-tw-adjuggler-tw-adjuggler-half-page-ad ##.pane-two-column-ads ##.pane_ad_wide ##.panel-ad ##.panel-advert ##.panel-body-adsense ##.panel__column--vc-advert ##.panel__row--with-vc-advert ##.panel_ad ##.paneladvert ##.partial-ad ##.partner-ad ##.partner-ads-container ##.partnerAd ##.partnerAdTable ##.partner_ads ##.partnerad_container ##.partnersTextLinks ##.patronad ##.pb-f-ad-flex ##.pb-mod-ad-flex ##.pb-mod-ad-leaderboard ##.pc-ad ##.pd-ads-mpu ##.peg_ad ##.pencil-ad ##.pencil-ad-container ##.pencil_ad ##.performancingads_region ##.pfAd ##.pfimgAds ##.pg-ad-block ##.pgAdSection_Home_MasterSponsers ##.photo-ad ##.photoad ##.photobox-adbox ##.pics_detail_ad ##.pics_footer_ad ##.picto_ad ##.pkgTemplateAdWrapper ##.pla_ad ##.placeholder-ad ##.placeholderAd ##.plainAd ##.play-page-ads ##.playAds1 ##.playAds2 ##.player-ads ##.player-leaderboard-ad-wrapper ##.player-under-ad ##.playerAd ##.player_ad ##.player_ad2 ##.player_ad_box ##.player_hover_ad ##.player_page_ad_box ##.plistaList > .itemLinkPET ##.plista_inimg_box ##.plista_widget_belowArticleRelaunch_item[data-type="pet"] ##.pm-ad ##.pm-banner-ad ##.pmad-in2 ##.pmg-sponsoredlinks ##.pn-ad ##.pn_dfpads ##.pnp_ad ##.pod-ad ##.pod-ad-300 ##.pod-ad-box ##.podRelatedAdLinksWidget ##.podSponsoredLink ##.poll_sponsor_ad ##.pop-up-ad ##.popadtext ##.popunder-adv ##.popup-ad ##.popupAd ##.popupAdOuter ##.popupAdWrapper ##.popup_ad ##.portalCenterContentAdBottom ##.portalCenterContentAdMiddle ##.portalCenterContentAdTop ##.portal_searchresultssponsoredlist ##.portalcontentad ##.pos_advert ##.post-ad ##.post-adsense-bottom ##.post-advert ##.post-advertisement ##.post-googlead ##.post-load-ad ##.post-nativeadcarousel ##.post-sponsored ##.postAd ##.postWideAd ##.post__ad ##.post__inarticle-ad-template ##.post_ad ##.post_ads ##.post_advert ##.post_seperator_ad ##.post_sponsor_unit ##.post_sponsored ##.postad ##.postads ##.postadsense ##.postbit_ad_block ##.postbit_adbit_register ##.postbit_adcode ##.postbody_ads ##.poster_ad ##.postfooterad ##.postgroup-ads ##.postgroup-ads-middle ##.power_by_sponsor ##.ppp_interior_ad ##.pq-ad ##.pr-ad-tower ##.pr-widget ##.pre-title-ad ##.prebodyads ##.premium-ad ##.premium-ads ##.premium-adv ##.premiumAdOverlay ##.premiumAdOverlayClose ##.premiumInHouseAd ##.premium_ad_container ##.premiumad ##.preview-ad ##.pricead-border ##.primary-ad ##.primary-advertisment ##.primary_sidebar_ad ##.printAds ##.pro_ad_adzone ##.pro_ad_system_ad_container ##.pro_ad_zone ##.prod_grid_ad ##.product-ads ##.product-inlist-ad ##.profile_ad_bottom ##.profile_ad_top ##.promo-ad ##.promo-box--ad ##.promo-class-brand-getprice ##.promoAd ##.promoAds ##.promoAdvertising ##.promo_ad ##.promo_border ##.promoad ##.promoboxAd ##.promotionTextAd ##.proof_ad ##.ps-ad ##.ps-ligatus_placeholder ##.pub_300x250 ##.pub_300x250m ##.pub_728x90 ##.publiboxright300 ##.publication-ad ##.publicidad ##.publicidadSuperior ##.publicidad_horizontal ##.publicidade-dotted ##.puff-ad ##.puff-advertorials ##.pull_top_ad ##.pulse360ad ##.pulsir-ad ##.puppyAd ##.push-ad ##.pushDownAd ##.pushdown-ad ##.pushdownAd ##.pw_wb_ad_300x250 ##.pwgAdWidget ##.pxz-ad-widget ##.pxz-taskbar-anchor ##.qa_ad_left ##.qm-ad ##.qm-ad-content ##.qm-ad-content-news ##.quick-tz-ad ##.quicklinks-ad ##.quigo ##.quigo-ad ##.quigoAdCenter ##.quigoAdRight ##.quigoMod ##.quigoads ##.quotead ##.qzvAdDiv ##.r_ad ##.r_ad_1 ##.r_ad_box ##.r_adbx_top ##.r_ads ##.r_col_add ##.rad_container ##.raff_ad ##.rail-ad ##.rail-article-sponsored ##.rail_ad ##.railad ##.railadspace ##.rbFooterSponsors ##.rbRectAd ##.rc_ad_300x100 ##.rc_ad_300x250 ##.rd_header_ads ##.rdio-homepage-widget ##.readerads ##.readermodeAd ##.realtor-ad ##.recentAds ##.recent_ad_holder ##.rect-ad ##.rect-ad-1 ##.rect_ad ##.rect_ad_module ##.rect_advert ##.rectad ##.rectadv ##.rectangle-ad ##.rectangle-ad-container ##.rectangle-embed-ad ##.rectangleAd ##.rectangleAdContainer ##.rectangle_ad ##.rectanglead ##.rectangleads ##.redads_cont ##.reedwan_adds300x250_widget ##.referrerDetailAd ##.refreshAds ##.refreshable_ad ##.region-ads ##.region-dfp-ad-content-bottom ##.region-dfp-ad-content-top ##.region-dfp-ad-footer ##.region-dfp-ad-header ##.region-header-ad ##.region-header-ads ##.region-leader-ad-bottom ##.region-leader-ad-top ##.region-middle-ad ##.region-regions-ad-top ##.region-regions-ad-top-inner ##.region-top-ad-position ##.region-widget-ad-top-0 ##.regular_728_ad ##.regularad ##.reklam ##.reklam-block ##.reklam2 ##.reklam728 ##.reklama ##.reklama-c ##.reklama-vert ##.reklama1 ##.reklame-right-col ##.reklame-wrapper ##.reklamka ##.rel_ad_box ##.related-ad ##.related-ads ##.related-al-ads ##.related-al-content-w150-ads ##.related-guide-adsense ##.relatedAds ##.relatedContentAd ##.related_post_google_ad ##.relatesearchad ##.remads ##.remnant_ad ##.remove-ads ##.removeAdsLink ##.reportAdLink ##.residentialads ##.resourceImagetAd ##.respAds ##.responsive-ad ##.result-ad ##.result-sponsored ##.resultAd ##.result_ad ##.result_item_ad-adsense ##.resultad ##.resultsAdsBlockCont ##.results_sponsor_right ##.rev_square_side_door ##.review-ad ##.reviewMidAdvertAlign ##.reviewpage_ad2 ##.reviews-box-ad ##.rf_circ_ad_460x205 ##.rght300x250 ##.rgt-300x250-ad ##.rgt-ad ##.rgt_ad ##.rhads ##.rhc-ad-bottom ##.rhs-ad ##.rhs-ads-panel ##.rhs-advert-container ##.rhs-advert-link ##.rhs-advert-title ##.rhs_ad_title ##.rhsad ##.rhsadvert ##.ribbon-ad-matte ##.right-ad ##.right-ad-300x250 ##.right-ad-block ##.right-ad-holder ##.right-ad2 ##.right-ads ##.right-ads2 ##.right-adsense ##.right-advert ##.right-col-ad ##.right-column-ad ##.right-navAdBox ##.right-rail-ad ##.right-rail-ad-banner ##.right-rail-broker-ads ##.right-side-ad ##.right-side-ads ##.right-sidebar-box-ad ##.right-sidebar-box-ads ##.right-square-ad-blocks ##.right-takeover-ad ##.right-takeover-ad-sticky ##.right-top-ad ##.rightAD ##.rightAd ##.rightAdBox ##.rightAdColumn ##.rightAdContainer ##.rightAd_bottom_fmt ##.rightAd_top_fmt ##.rightAds_ie_fix ##.rightAdvert ##.rightAdverts ##.rightBoxAd ##.rightBoxMidAds ##.rightColAd ##.rightColAdBox ##.rightColumnAd ##.rightColumnAdd ##.rightColumnAdsTop ##.rightColumnRectAd ##.rightHeaderAd ##.rightRailAd ##.rightRailMiddleAd ##.rightSecAds ##.rightSideBarAd ##.rightSideSponsor ##.rightTopAdWrapper ##.right_ad ##.right_ad_160 ##.right_ad_box ##.right_ad_box1 ##.right_ad_common_block ##.right_ad_innercont ##.right_ad_text ##.right_ad_top ##.right_ad_unit ##.right_ads ##.right_ads_column ##.right_adsense_box_2 ##.right_adv ##.right_advert ##.right_advertise_cnt ##.right_advertisement ##.right_block_advert ##.right_box_ad ##.right_box_ad_rotating_container ##.right_col_ad ##.right_col_ad_300_250 ##.right_column_ads ##.right_content_ad ##.right_content_ad_16 ##.right_google_ads ##.right_hand_advert_column ##.right_image_ad ##.right_long_ad ##.right_outside_ads ##.right_picAd ##.right_side-partyad ##.right_side_ads ##.right_side_box_ad ##.rightad ##.rightad250 ##.rightad_1 ##.rightad_2 ##.rightadbig ##.rightadblock ##.rightadbox1 ##.rightadd ##.rightads ##.rightadunit ##.rightadv ##.rightbigcolumn_ads ##.rightbigcolumn_ads_nobackground ##.rightbox_content_ads ##.rightboxads ##.rightcol-adbox ##.rightcol-block-ads ##.rightcol_boxad ##.rightcol_div_openx2 ##.rightcoladvert ##.rightcoltowerad ##.rightmenu_ad ##.rightnav_adsense ##.rightpanelad ##.rightrail-ad-block ##.rightrail_ads ##.rightsideAd ##.ringtone-ad ##.risingstar-ad ##.risingstar-ad-inner ##.riverSponsor ##.rmx-ad ##.rnav_ad ##.rngtAd ##.rockmelt-ad ##.rockmeltAdWrapper ##.rolloverad ##.rot_ads ##.rotating-ad ##.rotating-ads ##.rotatingAdvertisement ##.rotatingadsection ##.rotator_ad_overlay ##.round_box_advert ##.roundedCornersAd ##.roundingrayboxads ##.rowad ##.rowgoogleads ##.rr-300x250-ad ##.rr-300x600-ad ##.rr_ads ##.rr_skyad ##.rs_ad_bot ##.rs_ad_top ##.rside_adbox ##.rtAdFtr ##.rtSideHomeAd ##.rt_ad ##.rt_ad1_300x90 ##.rt_ad_300x250 ##.rt_ad_call ##.rt_advert_name ##.rt_el_advert ##.rtd_ads_text ##.rtmad ##.rtmm_right_ad ##.runner-ad ##.s-ad ##.s-ads ##.s2k_ad ##.sType-ad ##.s_ad ##.s_ad2 ##.s_ad_160x600 ##.s_ad_300x250 ##.s_ads ##.s_ads_label ##.s_sponsored_ads ##.sa_AdAnnouncement ##.sadvert ##.sam-ad ##.sam_ad ##.savvyad_unit ##.say-center-contentad ##.sb-ad ##.sb-ad-sq-bg ##.sb-ad2 ##.sb-ad3 ##.sb-ads-here ##.sbAd ##.sbAdUnitContainer ##.sbTopadWrapper ##.sb_ad ##.sb_ad_holder ##.sb_adsN ##.sb_adsNv2 ##.sb_adsW ##.sb_adsWv2 ##.sc-ad ##.sc_ad ##.sc_iframe_ad ##.scad ##.scanAd ##.scc_advert ##.schedule_ad ##.sci-ad-main ##.sci-ad-sub ##.scoopads ##.scraper_ad_unit ##.script-ad ##.scroll-ads ##.scrolling-ads ##.search-ad ##.search-advertisement ##.search-results-ad ##.search-sponsor ##.search-sponsored ##.searchAd ##.searchAdTop ##.searchAds ##.searchCenterBottomAds ##.searchCenterTopAds ##.searchResultAd ##.searchRightBottomAds ##.searchRightMiddleAds ##.searchSponsorItem ##.searchSponsoredResultsBox ##.searchSponsoredResultsList ##.search_ad_box ##.search_column_results_sponsored ##.search_inline_web_ad ##.search_results_ad ##.search_results_sponsored_top ##.searchad ##.searchads ##.sec-ad ##.secondary-advertisment ##.secondaryAdModule ##.secondary_ad ##.section-ad ##.section-ad-related ##.section-ad-wrapper ##.section-ad2 ##.section-adbox-bottom ##.section-adbox1 ##.section-ads ##.section-adtag ##.section-advert-banner ##.section-aside-ad ##.section_ad ##.section_ad_left ##.section_mpu_wrapper ##.section_mpu_wrapper_wrapper ##.selection-grid-advert ##.selfServeAds ##.seoTopAds ##.sepContentAd ##.series-ad ##.serp_sponsored ##.servedAdlabel ##.servsponserLinks ##.set_ad ##.sfsp_adadvert ##.sgAd ##.shadvertisment ##.shareToolsItemAd ##.shift-ad ##.shoppingGoogleAdSense ##.shortads ##.shortadvertisement ##.showAd ##.showAdContainer ##.showAd_No ##.showAd_Yes ##.showad_box ##.showcaseAd ##.showcasead ##.si-adRgt ##.sidbaread ##.side-ad ##.side-ad-120-bottom ##.side-ad-120-middle ##.side-ad-120-top ##.side-ad-160-bottom ##.side-ad-160-middle ##.side-ad-160-top ##.side-ad-300 ##.side-ad-300-bottom ##.side-ad-300-middle ##.side-ad-300-top ##.side-ad-big ##.side-ad-blocks ##.side-ad-container ##.side-ads ##.side-ads-block ##.side-ads-wide ##.side-ads300 ##.side-bar-ad-position1 ##.side-bar-ad-position2 ##.side-sky-banner-160 ##.side-video-ads-wrapper ##.sideAd ##.sideAdTall ##.sideAdWide ##.sideBannerAdsLarge ##.sideBannerAdsSmall ##.sideBannerAdsXLarge ##.sideBarAd ##.sideBarCubeAd ##.sideBlockAd ##.sideBoxAd ##.sideBoxM1ad ##.sideBoxMiddleAd ##.sideBySideAds ##.sideToSideAd ##.side_300_ad ##.side_ad ##.side_ad2 ##.side_ad300 ##.side_ad_1 ##.side_ad_2 ##.side_ad_3 ##.side_ads ##.side_adsense ##.side_adv ##.side_adv_01 ##.side_adv_left ##.side_adv_right ##.sidead ##.sidead_150 ##.sidead_300 ##.sidead_300250_ht ##.sidead_550125 ##.sideads ##.sideads_l ##.sideadsbox ##.sideadtable ##.sideadvert ##.sidebar-350ad ##.sidebar-ad ##.sidebar-ad-300 ##.sidebar-ad-300x250-cont ##.sidebar-ad-a ##.sidebar-ad-b ##.sidebar-ad-c ##.sidebar-ad-cont ##.sidebar-ad-container ##.sidebar-ad-container-1 ##.sidebar-ad-container-2 ##.sidebar-ad-container-3 ##.sidebar-ad-rect ##.sidebar-ad-slot ##.sidebar-adbox ##.sidebar-ads ##.sidebar-advertisement ##.sidebar-atf-ad-wrapper ##.sidebar-big-ad ##.sidebar-block-adsense ##.sidebar-box-ad ##.sidebar-box-ads ##.sidebar-content-ad ##.sidebar-header-ads ##.sidebar-paid-ad-label ##.sidebar-skyscraper-ad ##.sidebar-sponsors ##.sidebar-square-ad ##.sidebar-text-ad ##.sidebar-top-ad ##.sidebar300adblock ##.sidebarAd ##.sidebarAdBlock ##.sidebarAdNotice ##.sidebarAdUnit ##.sidebarAds300px ##.sidebarAdvert ##.sidebarCloseAd ##.sidebarNewsletterAd ##.sidebar_ADBOX ##.sidebar_ad ##.sidebar_ad_300 ##.sidebar_ad_300_250 ##.sidebar_ad_580 ##.sidebar_ad_container ##.sidebar_ad_container_div ##.sidebar_ad_holder ##.sidebar_ad_leaderboard ##.sidebar_ad_module ##.sidebar_ads ##.sidebar_ads-300x250 ##.sidebar_ads_336 ##.sidebar_ads_left ##.sidebar_ads_right ##.sidebar_ads_title ##.sidebar_adsense ##.sidebar_advertising ##.sidebar_box_ad ##.sidebar_right_ad ##.sidebar_skyscraper_ad ##.sidebar_small_ad ##.sidebarad ##.sidebarad160 ##.sidebarad_bottom ##.sidebaradbox ##.sidebaradcontent ##.sidebarads ##.sidebaradsense ##.sidebarboxad ##.sideheadnarrowad ##.sideheadsponsorsad ##.sidelist_ad ##.sideskyad ##.simple_ads_manager_block_widget ##.simple_ads_manager_widget ##.simple_ads_manager_zone_widget ##.simple_adsense_widget ##.simplead-container ##.simpleads-item ##.single-ad ##.single-ad-anchor ##.single-ad-wrap ##.single-ads ##.single-google-ad ##.single-post-ad ##.single-post-ads-750x90 ##.single-top-ad ##.singleAd ##.singleAdBox ##.singleAdsContainer ##.single_ad ##.single_advert ##.single_bottom_ad ##.single_fm_ad_bottom ##.single_top_ad ##.singlead ##.singleads ##.singleadstopcstm2 ##.singlepageleftad ##.singlepostad ##.singlepostadsense ##.singpagead ##.site-ad-block ##.site-ads ##.site-footer__ad-area ##.site-head-ads ##.site-top-ad ##.siteWideAd ##.site_ad ##.site_ad_120_600 ##.site_ad_300x250 ##.site_sponsers ##.sitesponsor ##.sitesprite_ads ##.skinAd ##.skin_ad_638 ##.skinad-l ##.skinad-r ##.sky-ad ##.skyAd ##.skyAdd ##.skyAdvert ##.skyAdvert2 ##.skyCraper_bannerLong ##.skyCraper_bannerShort ##.sky_ad ##.sky_ad_top ##.sky_scraper_ad ##.skyjobsadtext ##.skyscraper-ad ##.skyscraperAd ##.skyscraper_ad ##.skyscraper_bannerAdHome ##.skyscraper_banner_ad ##.sl-art-ad-midflex ##.sl-header-ad ##.sl_admarker ##.sleekadbubble ##.slide-ad ##.slideAd ##.slide_ad ##.sliderad ##.slideshow-ad ##.slideshow-ad-wrapper ##.slideshow-ads ##.slideshow-advertisement-note ##.slideshowAd ##.slideshow_ad_300 ##.slideshow_ad_note ##.slot_728_ad ##.slot_integrated_ad ##.slpBigSlimAdUnit ##.slpSquareAdUnit ##.sm-ad ##.smAdText_r ##.sm_ad ##.small-ad-header ##.small-ads ##.smallAd ##.smallAdContainer ##.smallAdvertisments ##.smallSkyAd1 ##.smallSkyAd2 ##.small_ad ##.small_ad_bg ##.small_ads ##.smallad ##.smallad-left ##.smalladblock ##.smallads ##.smalladscontainer ##.smalladword ##.smallbutton-adverts ##.smallsideadpane ##.smallsponsorad ##.smart_ads_bom_title ##.sml-item-ad ##.sn-ad-300x250 ##.snarcy-ad ##.snoadnetwork ##.social-ad ##.softronics-ad ##.southad ##.sp-ad ##.spLinks ##.spaceAdds ##.specialAd175x90 ##.specialAdsContent ##.specialAdsLabel ##.specialAdsLink ##.specialAdvertising ##.special_ad_section ##.specials_ads ##.speedyads ##.sphereAdContainer ##.spl-ads ##.spl_ad ##.spl_ad2 ##.spl_ad_plus ##.splitAd ##.splitAdResultsPane ##.splitter_ad ##.splitter_ad_holder ##.spn_links_box ##.spnsrAdvtBlk ##.spnsrCntnr ##.spon-links ##.spon125 ##.spon_link ##.sponadbox ##.sponlinkbox ##.spons-link ##.spons-wrap ##.sponsBox ##.sponsLinks ##.sponsWrap ##.spons_link_header ##.spons_links ##.sponser-link ##.sponserIABAdBottom ##.sponserLink ##.sponsersads ##.sponsertop ##.sponslink ##.sponsor-728 ##.sponsor-ad ##.sponsor-ad-wrapper ##.sponsor-area ##.sponsor-block ##.sponsor-bottom ##.sponsor-box ##.sponsor-btns ##.sponsor-left ##.sponsor-link ##.sponsor-links ##.sponsor-module-target ##.sponsor-post ##.sponsor-promo ##.sponsor-right ##.sponsor-services ##.sponsor-spot ##.sponsor-text ##.sponsor-text-container ##.sponsor120x600 ##.sponsor728x90 ##.sponsorArea ##.sponsorBannerWrapper ##.sponsorBlock ##.sponsorBottom ##.sponsorBox ##.sponsorBox_right_rdr ##.sponsorLabel ##.sponsorLink ##.sponsorLinks ##.sponsorMaskhead ##.sponsorPanel ##.sponsorPost ##.sponsorPostWrap ##.sponsorPuffsHomepage ##.sponsorStrip ##.sponsorText ##.sponsorTitle ##.sponsorTxt ##.sponsor_ad ##.sponsor_ad1 ##.sponsor_ad2 ##.sponsor_ad3 ##.sponsor_ad_area ##.sponsor_advert_link ##.sponsor_area ##.sponsor_bar ##.sponsor_block ##.sponsor_button_ad ##.sponsor_columns ##.sponsor_div ##.sponsor_div_title ##.sponsor_footer ##.sponsor_image ##.sponsor_label ##.sponsor_line ##.sponsor_links ##.sponsor_logo ##.sponsor_placement ##.sponsor_units ##.sponsorad ##.sponsoradlabel ##.sponsorads ##.sponsoradtitle ##.sponsored-ad ##.sponsored-ad-label ##.sponsored-ad-ob ##.sponsored-ads ##.sponsored-b ##.sponsored-chunk ##.sponsored-container-bottom ##.sponsored-default ##.sponsored-display-ad ##.sponsored-editorial ##.sponsored-features ##.sponsored-header ##.sponsored-headshop ##.sponsored-link ##.sponsored-links ##.sponsored-links-alt-b ##.sponsored-links-col ##.sponsored-links-holder ##.sponsored-links-right ##.sponsored-links-tbl ##.sponsored-offers-box ##.sponsored-post ##.sponsored-post_ad ##.sponsored-result ##.sponsored-result-row-2 ##.sponsored-results ##.sponsored-right ##.sponsored-right-border ##.sponsored-rule ##.sponsored-slot ##.sponsored-tag ##.sponsored-text ##.sponsored-title ##.sponsored-top ##.sponsoredAd ##.sponsoredAdLine ##.sponsoredAds ##.sponsoredBar ##.sponsoredBottom ##.sponsoredBox ##.sponsoredEntry ##.sponsoredFeature ##.sponsoredInfo ##.sponsoredInner ##.sponsoredLabel ##.sponsoredLeft ##.sponsoredLink ##.sponsoredLinks ##.sponsoredLinks2 ##.sponsoredLinksBox ##.sponsoredLinksGadget ##.sponsoredLinksHead ##.sponsoredLinksHeader ##.sponsoredName ##.sponsoredProduct ##.sponsoredResults ##.sponsoredSearch ##.sponsoredShowcasePanel ##.sponsoredSideInner ##.sponsoredStats ##.sponsoredTop ##.sponsored_ad ##.sponsored_ads ##.sponsored_box ##.sponsored_box_search ##.sponsored_by ##.sponsored_content ##.sponsored_glinks ##.sponsored_link ##.sponsored_links ##.sponsored_links2 ##.sponsored_links_box ##.sponsored_links_container ##.sponsored_links_section ##.sponsored_links_title_container ##.sponsored_links_title_container_top ##.sponsored_links_top ##.sponsored_result ##.sponsored_results ##.sponsored_ss ##.sponsored_text ##.sponsored_well ##.sponsoredby ##.sponsoredibbox ##.sponsoredlink ##.sponsoredlinkHed ##.sponsoredlinks ##.sponsoredlinks-article ##.sponsoredlinkscontainer ##.sponsoredresults ##.sponsoredtabl ##.sponsoredtextlink_container_ovt ##.sponsorheader ##.sponsoring_link ##.sponsoringbanner ##.sponsorlink ##.sponsorlink2 ##.sponsormsg ##.sponsors-box ##.sponsors-footer ##.sponsors-module ##.sponsorsBanners ##.sponsors_300x250 ##.sponsors_box_container ##.sponsors_fieldset ##.sponsors_links ##.sponsors_spacer ##.sponsorsbig ##.sponsorship-box ##.sponsorship-container ##.sponsorshipContainer ##.sponsorship_ad ##.sponsorshipbox ##.sponsorwrapper ##.sport-mpu-box ##.spot-ad ##.spotlight-ad ##.spotlight-ad-left ##.spotlightAd ##.sprite-ad_label_vert ##.sqAd2 ##.sq_ad ##.square-ad ##.square-ad--latest-video ##.square-ad--neg-margin ##.square-ad-1 ##.square-ad-container ##.square-advt ##.square-sidebar-ad ##.square-sponsorship ##.squareAd ##.squareAdWrap ##.squareAdd ##.squareAddtwo ##.squareAds ##.square_ad ##.square_ads ##.square_advert_inner ##.square_banner_ad ##.square_button_ads ##.squaread ##.squaread-container ##.squareads ##.squared_ad ##.sr-adsense ##.sr-in-feed-ads ##.sr-side-ad-block ##.sr_google_ad ##.src_parts_gen_ad ##.ss-ad-banner ##.ss-ad-mpu ##.ss-ad-tower ##.ss-ad_mrec ##.stProAd ##.stack-l-ad-center ##.stackedads1 ##.stackedads2 ##.stand-alone-adzone ##.standalone_txt_ad ##.standard-ad ##.star-ad ##.start__advertising_container ##.start__newest__big_game_container_body_games_advertising ##.start_overview_adv_container ##.statTop_adsense ##.staticAd ##.ste-ad ##.sticky-ad ##.sticky-ad-wrapper ##.stickyAdLink ##.sticky_ad_wrapper ##.stmAdHeightWidget ##.stock-ticker-ad-tag ##.stock_ad ##.stocks-ad-tag ##.store-ads ##.story-ad ##.story-page-embedded-ad ##.storyAdvert ##.storyInlineAdBlock ##.story_AD ##.story_ad_div ##.story_ads_right_spl ##.story_ads_right_spl_budget ##.story_body_advert ##.story_right_adv ##.storyad ##.storyad300 ##.stpro_ads ##.str-top-ad ##.stream-ad ##.streamAd ##.strip-ad ##.stripad ##.sub-feature-ad ##.sub-header-ad ##.subAdBannerArea ##.subAdBannerHeader ##.subNavAd ##.sub_cont_AD01 ##.sub_cont_AD02 ##.sub_cont_AD04 ##.sub_cont_AD06 ##.sub_cont_AD07 ##.subad ##.subadimg ##.subcontent-ad ##.subheadAdPanel ##.subheaderAdlogo ##.subheader_adsense ##.subjects_ad ##.submenu_ad ##.subtitle-ad-container ##.sugarad ##.suit-ad-inject ##.super-ad ##.superLeaderOverallAdArea ##.supercommentad_left ##.supercommentad_right ##.superscroll-ad ##.supp-ads ##.support-adv ##.supportAdItem ##.support_ad ##.surveyad ##.syAd ##.syHdrBnrAd ##.sykscraper-ad ##.szoAdBox ##.szoSponsoredPost ##.t10ad ##.tAd ##.tabAd ##.tabAds ##.tab_ad ##.tab_ad_area ##.table-ad ##.table_ad_bg ##.tablebordersponsor ##.taboola_advertising ##.tadsanzeige ##.tadsbanner ##.tadselement ##.tallAdvert ##.tallad ##.tangential-ad ##.tblAds ##.tblTopAds ##.tbl_ad ##.tbox_ad ##.tckr_adbrace ##.td-Adholder ##.td-TrafficWeatherWidgetAdGreyBrd ##.td-a-rec-id-custom_ad_1 ##.td-header-ad-wrap ##.td-header-sp-ads ##.tdAdHeader ##.tdBannerAd ##.tdFeaturedAdvertisers ##.td_ad ##.td_footer_ads ##.td_left_widget_ad ##.td_reklama_bottom ##.td_reklama_top ##.td_spotlight_ads ##.td_topads ##.tdad125 ##.teaser-ad ##.teaser-sponsor ##.teaserAdContainer ##.teaserAdHeadline ##.teaser_adtiles ##.teaser_advert_content ##.text-ad ##.text-ad-300 ##.text-ad-links ##.text-ad-links2 ##.text-ad-top ##.text-ads ##.text-advertisement ##.text-g-advertisement ##.text-g-group-short-rec-ad ##.text-g-net-group-news-half-page-ad-300x600-or-300x250 ##.text-g-net-grp-google-ads-article-page ##.text-g-nn-web-group-ad-halfpage ##.text-g-sponsored-ads ##.text-g-sponsored-links ##.textAd ##.textAd3 ##.textAdBG ##.textAdBlock ##.textAdBlwPgnGrey ##.textAdBox ##.textAdMinimum ##.textAds ##.textLinkAd ##.textSponsor ##.text_ad ##.text_ad_description ##.text_ad_title ##.text_ad_website ##.text_ads ##.text_ads_2 ##.textad ##.textadContainer ##.textad_headline ##.textadbox ##.textadheadline ##.textadlink ##.textads ##.textads_left ##.textads_right ##.textadscontainer ##.textadsds ##.textadsfoot ##.textadtext ##.textadtxt ##.textadtxt2 ##.textbanner-ad ##.textlink-ads ##.textlinkads ##.tf_page_ad_search ##.tfagAd ##.theAdvert ##.the_list_ad_zone ##.theleftad ##.themeblvd-ad-square-buttons ##.themidad ##.third-box-ad ##.third-party-ad ##.thirdAd160Cont ##.thirdAdBot ##.thirdAdHead ##.thirdage_ads_300x250 ##.thirdage_ads_728x90 ##.thisIsAd ##.thisIsAnAd ##.this_is_an_ad ##.thisisad ##.thread-ad ##.thread-ad-holder ##.threadAdsHeadlineData ##.three-ads ##.tibu_ad ##.ticket-ad ##.tile-ad ##.tileAdContainer ##.tileAdWrap ##.tileAds ##.tile_AdBanner ##.tile_ad_container ##.tips_advertisement ##.title-ad ##.title_adbig ##.tj_ad_box ##.tj_ad_box_top ##.tl-ad ##.tl-ad-dfp ##.tl-ad-display-3 ##.tl-ad-render ##.tm_ad200_widget ##.tm_topads_468 ##.tm_widget_ad200px ##.tmg-ad ##.tmg-ad-300x250 ##.tmg-ad-mpu ##.tmnAdsenseContainer ##.tmz-dart-ad ##.tncms-region-ads ##.toolad ##.toolbar-ad ##.toolsAd ##.toolssponsor-ads ##.top-300-ad ##.top-ad ##.top-ad-area ##.top-ad-block ##.top-ad-center ##.top-ad-container ##.top-ad-content ##.top-ad-horizontal ##.top-ad-inside ##.top-ad-right ##.top-ad-sidebar ##.top-ad-space ##.top-ad-unit ##.top-ad-wrapper ##.top-adbox ##.top-ads ##.top-ads-wrapper ##.top-adsense ##.top-adsense-banner ##.top-adspace ##.top-adv ##.top-adverbox ##.top-advert ##.top-advertisement ##.top-banner-468 ##.top-banner-ad ##.top-banner-ad-container ##.top-banner-ad-wrapper ##.top-banner-add ##.top-bar-ad-related ##.top-box-right-ad ##.top-content-adplace ##.top-header-ad ##.top-horiz-ad ##.top-item-ad ##.top-left-nav-ad ##.top-menu-ads ##.top-outer-ad-container ##.top-primary-sponsored ##.top-right-ad ##.top-right-advert ##.top-rightadvtsment ##.top-sidebar-adbox ##.top-treehouse-ad ##.top-wide-ad-container ##.top300ad ##.topAD ##.topAd728x90 ##.topAdBanner ##.topAdCenter ##.topAdContainer ##.topAdLeft ##.topAdRight ##.topAdWrap ##.topAdWrapper ##.topAdd ##.topAds ##.topAdvBox ##.topAdvert ##.topAdvertisement ##.topAdvertistemt ##.topAdverts ##.topArticleAds ##.topBannerAd ##.topBannerAdSectionR ##.topBarAd ##.topBoxAdvertisement ##.topLeaderboardAd ##.topNavRMAd ##.topPC-adWrap ##.topPagination_ad ##.topRightAd ##.top_Ad ##.top_ad ##.top_ad1 ##.top_ad_336x280 ##.top_ad_728 ##.top_ad_728_90 ##.top_ad_banner ##.top_ad_big ##.top_ad_disclaimer ##.top_ad_div ##.top_ad_holder ##.top_ad_inner ##.top_ad_label ##.top_ad_list ##.top_ad_long ##.top_ad_post ##.top_ad_seperate ##.top_ad_short ##.top_ad_wrap ##.top_ad_wrapper ##.top_adbox1 ##.top_adbox2 ##.top_adh ##.top_ads ##.top_adsense ##.top_adv ##.top_adv_content ##.top_advert ##.top_advertisement ##.top_advertising_lb ##.top_advertizing_cnt ##.top_bar_ad ##.top_big_ads ##.top_container_ad ##.top_corner_ad ##.top_header_ad ##.top_header_ad_inner ##.top_right_ad ##.top_rightad ##.top_sponsor ##.topad-area ##.topad-bar ##.topad-bg ##.topad2 ##.topadbar ##.topadblock ##.topadbox ##.topads ##.topads-spacer ##.topadspace ##.topadspot ##.topadtara ##.topadvertisementsegment ##.topbar-ad-unit ##.topboardads ##.topcontentadvertisement ##.topfootad ##.topicDetailsAdRight ##.topic_inad ##.topnavSponsor ##.topratedBoxAD ##.topsidebarad ##.topstoriesad ##.toptenAdBoxA ##.tourFeatureAd ##.tower-ad ##.tower-ad-abs ##.tower-ads-container ##.towerAd ##.towerAdLeft ##.towerAds ##.tower_ad ##.tower_ad_disclaimer ##.towerad ##.tp-ad-label ##.tp_ads ##.tr-ad-adtech-placement ##.tr-ad-inset ##.trafficAdSpot ##.trb_gptAd ##.trb_header_adBanner_large ##.trb_masthead_adBanner ##.trb_pageAdHolder ##.trc-content-sponsored ##.trc-content-sponsoredUB ##.treeAdBlockWithBanner_right ##.tribal-ad ##.trip_ad_center ##.trueads ##.ts-ad_unit_bigbox ##.ts-banner_ad ##.ts-featured_ad ##.tsmAd ##.ttlAdsensel ##.tto-sponsored-element ##.tucadtext ##.tvs-mpu ##.two-col-ad-inArticle ##.twoColumnAd ##.two_ads ##.twoadcoll ##.twoadcolr ##.tx_smartadserver_pi1 ##.txt-ads ##.txtAd ##.txtAd5 ##.txtAds ##.txt_ad ##.txt_ads ##.txtad_area ##.txtadvertise ##.tynt-ad-container ##.type_ads_default ##.type_adscontainer ##.type_miniad ##.type_promoads ##.tz_ad300_widget ##.tz_ad_widget ##.uds-ad ##.uds-ads ##.ui-ad ##.ukAds ##.ukn-banner-ads ##.ukn-inline-advert ##.unSponsored ##.under-player-ads ##.under_ads ##.undertimyads ##.uniAdBox ##.uniAds ##.uniblue-text-ad ##.unit-ad ##.universalboxADVBOX01 ##.universalboxADVBOX03 ##.universalboxADVBOX04a ##.unspoken-adplace ##.upcloo-adv-content ##.upper-ad-space ##.us-advertisement ##.us-txt-ad ##.useful_banner_manager_rotation_widget ##.useful_banner_manager_widget ##.usenext ##.v5rc_336x280ad ##.vAd_160x600 ##.vadvert ##.vbox-verticalad ##.ve2_post_adsense ##.vert-ad ##.vert-ad-ttl ##.vert-ads ##.vert-adsBlock ##.vertad ##.vertical-adsense ##.verticalAd ##.verticalAdText ##.vertical_ad ##.vertical_ads ##.verticalad ##.verysmallads ##.vidadtext ##.video-about-ad ##.video-ad-short ##.video-ads ##.video-adtech-mpu-ad ##.video-innerAd-320x250 ##.videoAd-wrapper ##.videoBoxAd ##.video_ad ##.video_ads ##.video_ads_overdiv ##.video_ads_overdiv2 ##.video_advertisement_box ##.video_detail_box_ads ##.video_top_ad ##.view-adverts ##.view-image-ads ##.view-promo-mpu-right ##.view-site-ads ##.view-video-advertisements ##.viewContentItemAd ##.view_ad ##.view_ads_advertisements ##.view_ads_bottom_bg ##.view_ads_bottom_bg_middle ##.view_ads_content_bg ##.view_ads_top_bg ##.view_ads_top_bg_middle ##.view_rig_ad ##.views-field-field-ad ##.views-field-field-adbox-1 ##.views-field-field-adbox-2 ##.virgin-mpu ##.vl-ad-item ##.vod_ad ##.vs-advert-300x250 ##.vs_dfp_standard_postbit_ad ##.vsw-ads ##.vswAdContainer ##.vt_h1_ad ##.vxp_ad300x250 ##.w-ad-box ##.wAdvert ##.w_AdExternal ##.wa_adsbottom ##.wahAd ##.wahAdRight ##.wallAd ##.wall_ad ##.wall_ad_hd ##.wallad ##.wantads ##.waterfall-ad-anchor ##.wazi-ad-link ##.wd-adunit ##.wdca_ad_item ##.wdca_custom_ad ##.wdp_ad ##.wdp_adDiv ##.wdt_ads ##.weather-ad-wrapper ##.weather-sponsor-ad ##.weather-sponsorDiv ##.weatherAdSpot ##.weather_ad ##.weatherad ##.web-result-sponsored ##.webad-cnt ##.webads336x280 ##.webadvert-container ##.well-ad ##.wfb-ad ##.wg-ad-square ##.wide-ad ##.wide-ad-container ##.wide-ad-outer ##.wide-advert ##.wide-footer-ad ##.wide-header-ad ##.wide-skyscraper-ad ##.wideAd ##.wideAdTable ##.widePageAd ##.wide_ad ##.wide_ad_unit ##.wide_ad_unit_top ##.wide_ads ##.wide_google_ads ##.wide_grey_ad_box ##.wide_sponsors ##.widead ##.wideadbox ##.widget-ad ##.widget-ad-codes ##.widget-ad-sky ##.widget-ad-zone ##.widget-ad300x250 ##.widget-adcode ##.widget-ads ##.widget-adsense ##.widget-adv ##.widget-advertisement ##.widget-entry-ads-160 ##.widget-group-Ads ##.widget-highlight-ads ##.widget-text-ad ##.widgetAdScrollContainer ##.widgetYahooAds ##.widget_ad ##.widget_ad-widget ##.widget_ad125 ##.widget_ad_300x250_atf ##.widget_ad_300x250_btf ##.widget_ad_300x250_btf_b ##.widget_ad_boxes_widget ##.widget_ad_rotator ##.widget_ad_widget ##.widget_admanagerwidget ##.widget_adrotate_widgets ##.widget_ads ##.widget_adsblock ##.widget_adsensem ##.widget_adsensewidget ##.widget_adsingle ##.widget_adv_location ##.widget_advert_content ##.widget_advert_widget ##.widget_advertisement ##.widget_advertisements ##.widget_advertisment ##.widget_advwidget ##.widget_adwidget ##.widget_bestgoogleadsense ##.widget_boss_banner_ad ##.widget_catchbox_adwidget ##.widget_cevo_contentad ##.widget_customadvertising ##.widget_cxad ##.widget_econaabachoadswidget ##.widget_emads ##.widget_fearless_responsive_image_ad ##.widget_googleads ##.widget_ima_ads ##.widget_internationaladserverwidget ##.widget_ione-dart-ad ##.widget_island_ad ##.widget_maxbannerads ##.widget_nb-ads ##.widget_new_sponsored_content ##.widget_openxwpwidget ##.widget_plugrush_widget ##.widget_sdac_bottom_ad_widget ##.widget_sdac_companion_video_ad_widget ##.widget_sdac_footer_ads_widget ##.widget_sdac_skyscraper_ad_widget ##.widget_sdac_top_ad_widget ##.widget_sej_sidebar_ad ##.widget_sidebarad_300x250 ##.widget_sidebarad_300x600 ##.widget_sidebaradwidget ##.widget_sponsored_content ##.widget_uds-ads ##.widget_vb_sidebar_ad ##.widget_wnd_ad_widget ##.widget_wpshower_ad ##.widgetads ##.width-ad-slug ##.wikia-ad ##.wikia_ad_placeholder ##.wingadblock ##.wis_adControl ##.withAds ##.wixAdsdesktopBottomAd ##.wl-ad ##.wn-ad ##.wnIframeAd ##.wnMultiAd ##.wnad ##.wp125_write_ads_widget ##.wp125ad ##.wp125ad_1 ##.wp125ad_2 ##.wpInsertInPostAd ##.wp_bannerize ##.wpadvert ##.wpbrad ##.wpbrad-ad ##.wpbrad-zone ##.wpfp_custom_ad ##.wpi_ads ##.wpn_ad_content ##.wpproadszone ##.wptouch-ad ##.wpx-bannerize ##.wrap-ads ##.wrap_boxad ##.wrapad ##.wrapper-ad ##.wrapper-ad-sidecol ##.wrapper-google-ads ##.wrapper_ad ##.ws-ad ##.wsSearchResultsRightSponsoredLinks ##.wsSponsoredLinksRight ##.wsTopSposoredLinks ##.wx-adchoices ##.wx-gptADS ##.x-ad ##.x-home-ad__content ##.x-home-ad__content-inner ##.x01-ad ##.x03-adunit ##.x04-adunit ##.x81_ad_detail ##.xads-blk-bottom-hld ##.xads-blk-top-hld ##.xads-blk-top2-hld ##.xads-blk1 ##.xads-blk2 ##.xads-ojedn ##.xmlad ##.xs_epic_circ_ad ##.xs_epic_sponsor_label ##.xtopadvert ##.y-ads ##.y-ads-wide ##.y5_ads ##.y5_ads2 ##.y7-advertisement ##.y7adHEAD ##.y7adS ##.y7s-lrec ##.yaAds ##.yad-sponsored ##.yahoo-ad-leader-north ##.yahoo-ad-leader-south ##.yahoo-ad-lrec-north ##.yahoo-banner-ad-container ##.yahoo-sponsored ##.yahoo-sponsored-links ##.yahoo-sponsored-result ##.yahooAd ##.yahooAds ##.yahooContentMatch ##.yahoo_ad ##.yahoo_ads ##.yahooad-image ##.yahooad-urlline ##.yahooads ##.yahootextads_content_bottom ##.yam-plus-ad-container ##.yan-sponsored ##.yat-ad ##.yellow_ad ##.yfi-fp-ad-logo ##.ygrp-ad ##.yieldads-160x600 ##.yieldads-728x90 ##.yl-lrec-wrap ##.yls-sponlink ##.yom-ad ##.yom-ad-LREC ##.yom-ad-LREC2 ##.yom-ad-LREC3 ##.yom-ad-MREC2 ##.yom-ad-moneyball ##.youradhere ##.youtubeSuperLeaderBoardAdHolder ##.youtubeSuperLeaderOverallAdArea ##.yrail_ad_wrap ##.yrail_ads ##.ysmsponsor ##.ysp-dynamic-ad ##.ysponsor ##.yt-adsfull-widget ##.yui3-ad ##.yw-ad ##.z-sponsored-block ##.zRightAdNote ##.zc-grid-ad ##.zc-grid-position-ad ##.zem_rp_promoted ##.zeti-ads ##[onclick^="window.open('http://adultfriendfinder.com/search/"] ##a[data-redirect^="this.href='http://paid.outbrain.com/network/redir?"] ##a[href$="/vghd.shtml"] ##a[href*="/adrotate-out.php?"] ##a[href^=" http://ads.ad-center.com/"] ##a[href^="//adbit.co/?a=Advertise&"] ##a[href^="//ads.ad-center.com/"] ##a[href^="http://1phads.com/"] ##a[href^="http://360ads.go2cloud.org/"] ##a[href^="http://NowDownloadAll.com"] ##a[href^="http://ad-apac.doubleclick.net/"] ##a[href^="http://ad-emea.doubleclick.net/"] ##a[href^="http://ad.au.doubleclick.net/"] ##a[href^="http://ad.doubleclick.net/"] ##a[href^="http://ad.yieldmanager.com/"] ##a[href^="http://adexprt.me/"] ##a[href^="http://adf.ly/?id="] ##a[href^="http://adfarm.mediaplex.com/"] ##a[href^="http://adlev.neodatagroup.com/"] ##a[href^="http://ads.activtrades.com/"] ##a[href^="http://ads.ad-center.com/"] ##a[href^="http://ads.affbuzzads.com/"] ##a[href^="http://ads.betfair.com/redirect.aspx?"] ##a[href^="http://ads.integral-marketing.com/"] ##a[href^="http://ads.pheedo.com/"] ##a[href^="http://ads2.williamhill.com/redirect.aspx?"] ##a[href^="http://adserver.adtech.de/"] ##a[href^="http://adserver.adtechus.com/"] ##a[href^="http://adserver.itsfogo.com/"] ##a[href^="http://adserving.liveuniversenetwork.com/"] ##a[href^="http://adserving.unibet.com/"] ##a[href^="http://adsrv.keycaptcha.com"] ##a[href^="http://adtransfer.net/"] ##a[href^="http://adultfriendfinder.com/p/register.cgi?pid="] ##a[href^="http://affiliate.coral.co.uk/processing/"] ##a[href^="http://affiliate.glbtracker.com/"] ##a[href^="http://affiliate.godaddy.com/"] ##a[href^="http://affiliates.score-affiliates.com/"] ##a[href^="http://aflrm.com/"] ##a[href^="http://amzn.to/"] > img[src^="data"] ##a[href^="http://api.ringtonematcher.com/"] ##a[href^="http://api.taboola.com/"][href*="/recommendations.notify-click?app.type="] ##a[href^="http://at.atwola.com/"] ##a[href^="http://banners.victor.com/processing/"] ##a[href^="http://bc.vc/?r="] ##a[href^="http://bcp.crwdcntrl.net/"] ##a[href^="http://bestorican.com/"] ##a[href^="http://bluehost.com/track/"] ##a[href^="http://bonusfapturbo.nmvsite.com/"] ##a[href^="http://bs.serving-sys.com/"] ##a[href^="http://buysellads.com/"] ##a[href^="http://c.actiondesk.com/"] ##a[href^="http://campaign.bharatmatrimony.com/track/"] ##a[href^="http://cdn3.adexprts.com/"] ##a[href^="http://centertrust.xyz/"] ##a[href^="http://chaturbate.com/affiliates/"] ##a[href^="http://cinema.friendscout24.de?"] ##a[href^="http://clickandjoinyourgirl.com/"] ##a[href^="http://clickserv.sitescout.com/"] ##a[href^="http://clk.directrev.com/"] ##a[href^="http://clkmon.com/adServe/"] ##a[href^="http://codec.codecm.com/"] ##a[href^="http://connectlinking6.com/"] ##a[href^="http://cpaway.afftrack.com/"] ##a[href^="http://d2.zedo.com/"] ##a[href^="http://data.ad.yieldmanager.net/"] ##a[href^="http://databass.info/"] ##a[href^="http://down1oads.com/"] ##a[href^="http://dwn.pushtraffic.net/"] ##a[href^="http://easydownload4you.com/"] ##a[href^="http://elitefuckbook.com/"] ##a[href^="http://feedads.g.doubleclick.net/"] ##a[href^="http://fileloadr.com/"] ##a[href^="http://finaljuyu.com/"] ##a[href^="http://freesoftwarelive.com/"] ##a[href^="http://fsoft4down.com/"] ##a[href^="http://fusionads.net"] ##a[href^="http://galleries.pinballpublishernetwork.com/"] ##a[href^="http://galleries.securewebsiteaccess.com/"] ##a[href^="http://games.ucoz.ru/"][target="_blank"] ##a[href^="http://gca.sh/user/register?ref="] ##a[href^="http://getlinksinaseconds.com/"] ##a[href^="http://go.seomojo.com/tracking202/"] ##a[href^="http://greensmoke.com/"] ##a[href^="http://hd-plugins.com/download/"] ##a[href^="http://hdplugin.flashplayer-updates.com/"] ##a[href^="http://hyperlinksecure.com/go/"] ##a[href^="http://install.securewebsiteaccess.com/"] ##a[href^="http://k2s.cc/pr/"] ##a[href^="http://keep2share.cc/pr/"] ##a[href^="http://landingpagegenius.com/"] ##a[href^="http://latestdownloads.net/download.php?"] ##a[href^="http://lp.ezdownloadpro.info/"] ##a[href^="http://lp.ilivid.com/"] ##a[href^="http://lp.ncdownloader.com/"] ##a[href^="http://marketgid.com"] ##a[href^="http://mgid.com/"] ##a[href^="http://n.admagnet.net/"] ##a[href^="http://online.ladbrokes.com/promoRedirect?"] ##a[href^="http://paid.outbrain.com/network/redir?"][target="_blank"] ##a[href^="http://partner.sbaffiliates.com/"] ##a[href^="http://pokershibes.com/index.php?ref="] ##a[href^="http://pubads.g.doubleclick.net/"] ##a[href^="http://refer.webhostingbuzz.com/"] ##a[href^="http://ryushare.com/affiliate.python"] ##a[href^="http://secure.hostgator.com/~affiliat/"] ##a[href^="http://secure.signup-page.com/"] ##a[href^="http://secure.signup-way.com/"] ##a[href^="http://serve.williamhill.com/promoRedirect?"] ##a[href^="http://server.cpmstar.com/click.aspx?poolid="] ##a[href^="http://sharesuper.info/"] ##a[href^="http://t.wowtrk.com/"] ##a[href^="http://taboola-"][href*="/redirect.php?app.type="] ##a[href^="http://tour.affbuzzads.com/"] ##a[href^="http://track.adform.net/"] ##a[href^="http://tracking.crazylead.com/"] ##a[href^="http://tracking.deltamediallc.com/"] ##a[href^="http://ul.to/ref/"] ##a[href^="http://uploaded.net/ref/"] ##a[href^="http://us.marketgid.com"] ##a[href^="http://www.123-reg.co.uk/affiliate2.cgi"] ##a[href^="http://www.1clickdownloader.com/"] ##a[href^="http://www.1clickmoviedownloader.info/"] ##a[href^="http://www.FriendlyDuck.com/AF_"] ##a[href^="http://www.TwinPlan.com/AF_"] ##a[href^="http://www.adbrite.com/mb/commerce/purchase_form.php?"] ##a[href^="http://www.adshost2.com/"] ##a[href^="http://www.adxpansion.com"] ##a[href^="http://www.affbuzzads.com/affiliate/"] ##a[href^="http://www.amazon.co.uk/exec/obidos/external-search?"] ##a[href^="http://www.babylon.com/welcome/index?affID"] ##a[href^="http://www.badoink.com/go.php?"] ##a[href^="http://www.bet365.com/home/?affiliate"] ##a[href^="http://www.clickansave.net/"] ##a[href^="http://www.clkads.com/adServe/"] ##a[href^="http://www.dealcent.com/register.php?affid="] ##a[href^="http://www.dl-provider.com/search/"] ##a[href^="http://www.down1oads.com/"] ##a[href^="http://www.download-provider.org/"] ##a[href^="http://www.downloadthesefiles.com/"] ##a[href^="http://www.downloadweb.org/"] ##a[href^="http://www.drowle.com/"] ##a[href^="http://www.epicgameads.com/"] ##a[href^="http://www.faceporn.net/free?"] ##a[href^="http://www.fbooksluts.com/"] ##a[href^="http://www.firstclass-download.com/"] ##a[href^="http://www.firstload.com/affiliate/"] ##a[href^="http://www.firstload.de/affiliate/"] ##a[href^="http://www.fleshlight.com/"] ##a[href^="http://www.fonts.com/BannerScript/"] ##a[href^="http://www.fpcTraffic2.com/blind/in.cgi?"] ##a[href^="http://www.freefilesdownloader.com/"] ##a[href^="http://www.friendlyduck.com/AF_"] ##a[href^="http://www.google.com/aclk?"] ##a[href^="http://www.graboid.com/affiliates/"] ##a[href^="http://www.idownloadplay.com/"] ##a[href^="http://www.incredimail.com/?id="] ##a[href^="http://www.ireel.com/signup?ref"] ##a[href^="http://www.linkbucks.com/referral/"] ##a[href^="http://www.liutilities.com/"] ##a[href^="http://www.menaon.com/installs/"] ##a[href^="http://www.mobileandinternetadvertising.com/"] ##a[href^="http://www.my-dirty-hobby.com/?sub="] ##a[href^="http://www.myfreepaysite.com/sfw.php?aid"] ##a[href^="http://www.myfreepaysite.com/sfw_int.php?aid"] ##a[href^="http://www.mysuperpharm.com/"] ##a[href^="http://www.myvpn.pro/"] ##a[href^="http://www.on2url.com/app/adtrack.asp"] ##a[href^="http://www.paddypower.com/?AFF_ID="] ##a[href^="http://www.pheedo.com/"] ##a[href^="http://www.pinkvisualgames.com/?revid="] ##a[href^="http://www.plus500.com/?id="] ##a[href^="http://www.quick-torrent.com/download.html?aff"] ##a[href^="http://www.revenuehits.com/"] ##a[href^="http://www.ringtonematcher.com/"] ##a[href^="http://www.roboform.com/php/land.php"] ##a[href^="http://www.seekbang.com/cs/"] ##a[href^="http://www.sex.com/?utm_source="] ##a[href^="http://www.sfippa.com/"] ##a[href^="http://www.socialsex.com/"] ##a[href^="http://www.streamate.com/exports/"] ##a[href^="http://www.streamtunerhd.com/signup?"] ##a[href^="http://www.text-link-ads.com/"] ##a[href^="http://www.torntv-downloader.com/"] ##a[href^="http://www.torntvdl.com/"] ##a[href^="http://www.uniblue.com/cm/"] ##a[href^="http://www.urmediazone.com/signup"] ##a[href^="http://www.usearchmedia.com/signup?"] ##a[href^="http://www.wantstraffic.com/"] ##a[href^="http://www.webtrackerplus.com/"] ##a[href^="http://www.yourfuckbook.com/?"] ##a[href^="http://www1.clickdownloader.com/"] ##a[href^="http://wxdownloadmanager.com/dl/"] ##a[href^="http://xads.zedo.com/"] ##a[href^="http://yads.zedo.com/"] ##a[href^="http://z1.zedo.com/"] ##a[href^="http://zevera.com/afi.html"] ##a[href^="https://ad.doubleclick.net/"] ##a[href^="https://bs.serving-sys.com"] ##a[href^="https://dltags.com/"] ##a[href^="https://secure.eveonline.com/ft/?aid="] ##a[href^="https://www.FriendlyDuck.com/AF_"] ##a[href^="https://www.dsct1.com/"] ##a[href^="https://www.firstload.com/affiliate/"] ##a[href^="https://www.oboom.com/ad/"] ##a[href^="https://www.share-online.biz/affiliate/"] ##a[onmousedown^="this.href='http://paid.outbrain.com/network/redir?"][target="_blank"] ##a[onmousedown^="this.href='http://paid.outbrain.com/network/redir?"][target="_blank"] + .ob_source ##a[onmousedown^="this.href='http://staffpicks.outbrain.com/network/redir?"][target="_blank"] ##a[onmousedown^="this.href='http://staffpicks.outbrain.com/network/redir?"][target="_blank"] + .ob_source ##a[onmousedown^="this.href='https://paid.outbrain.com/network/redir?"][target="_blank"] ##a[onmousedown^="this.href='https://paid.outbrain.com/network/redir?"][target="_blank"] + .ob_source ##a[style="display:block;width:300px;min-height:250px"][href^="http://li.cnet.com/click?"] ##div[id^="MarketGid"] ##div[id^="YFBMSN"] ##div[id^="acm-ad-tag-"] ##div[id^="div-gpt-ad-"] ##iframe[id^="google_ads_frame"] ##iframe[id^="google_ads_iframe"] ##iframe[src^="http://ad.yieldmanager.com/"] ##iframe[src^="http://cdn1.adexprt.com/"] ##iframe[src^="http://cdn2.adexprt.com/"] ##img[alt^="Fuckbook"] ##input[onclick^="window.open('http://www.FriendlyDuck.com/AF_"] ##input[onclick^="window.open('http://www.friendlyduck.com/AF_"] ##p[id^="div-gpt-ad-"] ##script[src^="http://free-shoutbox.net/app/webroot/shoutbox/sb.php?shoutbox="] + #freeshoutbox_content ! In advert promo ##.brandpost_inarticle ! Forumotion.com related sites ###main-content > [style="padding:10px 0 0 0 !important;"] ##td[valign="top"] > .mainmenu[style="padding:10px 0 0 0 !important;"] ! Whistleout widget ###rhs_whistleout_widget ###wo-widget-wrap ! Asset Listings ###assetsListings[style="display: block;"] ! Magnify transparient advert on video ###magnify_widget_playlist_item_companion ! Playbb.me / easyvideo.me / videozoo.me / paypanda.net ###flowplayer > div[style="position: absolute; width: 300px; height: 275px; left: 222.5px; top: 85px; z-index: 999;"] ###flowplayer > div[style="z-index: 208; position: absolute; width: 300px; height: 275px; left: 222.5px; top: 85px;"] ##.Mpopup + #Mad > #MadZone ! https://adblockplus.org/forum/viewtopic.php?f=2&t=17016 ##.l-container > #fishtank ! Google ###center_col > #\5f Emc ###center_col > #resultStats + #tads ###center_col > #resultStats + #tads + #res + #tads ###center_col > #resultStats + div + #res + #tads ###center_col > #resultStats + div[style="border:1px solid #dedede;margin-bottom:11px;padding:5px 7px 5px 6px"] ###center_col > #taw > #tvcap > .rscontainer ###center_col > div[style="font-size:14px;margin-right:0;min-height:5px"] > div[style="font-size:14px;margin:0 4px;padding:1px 5px;background:#fff8e7"] ###cnt #center_col > #res > #topstuff > .ts ###main_col > #center_col div[style="font-size:14px;margin:0 4px;padding:1px 5px;background:#fff7ed"] ###mbEnd[cellspacing="0"][cellpadding="0"] ###mclip_container:last-child ###mn #center_col > div > h2.spon:first-child ###mn #center_col > div > h2.spon:first-child + ol:last-child ###resultspanel > #topads ###rhs_block > #mbEnd ###rhs_block > .ts[cellspacing="0"][cellpadding="0"][style="padding:0"] ###rhs_block > ol > .rhsvw > .kp-blk > .xpdopen > ._OKe > ol > ._DJe > .luhb-div ###rhswrapper > #rhssection[border="0"][bgcolor="#ffffff"] ###ssmiwdiv[jsdisplay] ###tads + div + .c ###tads.c ###tadsb.c ###tadsto.c ###topstuff > #tads ##.GB3L-QEDGY .GB3L-QEDF- > .GB3L-QEDE- ##.GFYY1SVD2 > .GFYY1SVC2 > .GFYY1SVF5 ##.GFYY1SVE2 > .GFYY1SVD2 > .GFYY1SVG5 ##.GHOFUQ5BG2 > .GHOFUQ5BF2 > .GHOFUQ5BG5 ##.GJJKPX2N1 > .GJJKPX2M1 > .GJJKPX2P4 ##.GKJYXHBF2 > .GKJYXHBE2 > .GKJYXHBH5 ##.GPMV2XEDA2 > .GPMV2XEDP1 > .GPMV2XEDJBB ##.ch[onclick="ga(this,event)"] ##.commercial-unit-desktop-rhs ##.commercial-unit-desktop-top ##.lads[width="100%"][style="background:#FFF8DD"] ##.mod > ._jH + .rscontainer ##.mw > #rcnt > #center_col > #taw > #tvcap > .c ##.mw > #rcnt > #center_col > #taw > .c ##.ra[align="left"][width="30%"] ##.ra[align="right"][width="30%"] ##.ra[width="30%"][align="right"] + table[width="70%"][cellpadding="0"] ##.rhsvw[style="background-color:#fff;margin:0 0 14px;padding-bottom:1px;padding-top:1px;"] ##.rscontainer > .ellip ! Sedo ###ads > .dose > .dosesingle ###content > #center > .dose > .dosesingle ###content > #right > .dose > .dosesingle ###header + #content > #left > #rlblock_left ! Taboola ###recommendations a[rel="nofollow"][onclick^="window.open('http://api.taboola.com/"][href="#"] ##.trc_rbox .syndicatedItem ##.trc_rbox_border_elm .syndicatedItem ##.trc_rbox_div .syndicatedItem ##.trc_rbox_div .syndicatedItemUB ##.trc_rbox_div a[target="_blank"][href^="http://tab"] ##.trc_related_container div[data-item-syndicated="true"] ! Tripadvisor ###MAIN.ShowTopic > .ad ! uCoz ! https://adblockplus.org/forum/viewtopic.php?f=2&t=13414 ##div[id^="mainads"] ! yavli.com Sponsored content ##.__y_elastic .__y_item ##.__y_inner > .__y_item ##.__y_outer ##.__yinit .__y_item ##.__ywl .__y_item ##.__ywvr .__y_item ##.__zinit .__y_item ##.icons-rss-feed + .icons-rss-feed div[class$="_item"] ##.inlineNewsletterSubscription + .inlineNewsletterSubscription div[class$="_item"] ##.jobs-information-call-to-action + .jobs-information-call-to-action div[class$="_item"] ! zergnet ###boxes-box-zergnet_module ###zergnet ###zergnet-widget ###zergnet-wrapper ##.module-zerg ##.widget-ami-zergnet ##.widget_ok_zergnet_widget ##.zergnet ##.zergnet-widget-container ##.zergnetBLock ##.zergnetpower ##div[id^="zergnet-widget-"] ! *** easylist:easylist/easylist_whitelist_general_hide.txt *** thedailygreen.com#@##AD_banner webmail.verizon.net#@##AdColumn jobs.wa.gov.au,lalovings.com#@##AdContainer jobs.wa.gov.au,ksl.com#@##AdHeader sprouts.com,tbns.com.au#@##AdImage games.com#@##Adcode designspotter.com#@##AdvertiseFrame wikimedia.org,wikipedia.org#@##Advertisements newser.com#@##BottomAdContainer freeshipping.com,freeshippingrewards.com#@##BottomAds orientaldaily.on.cc#@##ContentAd kizi.com,playedonline.com#@##PreRollAd japantimes.co.jp#@##RightAdBlock isource.com,nytimes.com#@##TopAd dailyfinancegroup.com#@##ad-area dormy.se,marthastewart.com#@##ad-background chinradioottawa.com#@##ad-bg fropper.com,themonthly.com.au#@##ad-container apnaohio.com,ifokus.se,miradiorumba.com#@##ad-header egreetings.com#@##ad-header-728x90 elle.com#@##ad-leaderboard chicagocrusader.com,garycrusader.com#@##ad-main harpcolumn.com#@##ad-text gismeteo.com,gismeteo.lt,gismeteo.lv,gismeteo.md#@##ad-top afterdawn.com#@##ad-top-banner-placeholder babyzone.com#@##ad-top-wrapper edgesuite.net#@##ad-unit amctv.com,collegeslackers.com,ufoevidence.org,wg-gesucht.de#@##ad-wrapper egotastic.com,nehandaradio.com#@##ad468 bristol247.com,zap2it.com#@##ad728 natgeo.tv#@##ad728x90 campusdish.com#@##adBanner 4029tv.com,wesh.com,wmur.com#@##adBelt imdb.com#@##adComponentWrapper remixshare.com#@##adDiv surf.to#@##adFrame ginatricot.com#@##adGallery jobs.wa.gov.au,ksl.com#@##adHeader indecisionforever.com#@##adHolder youkioske.com#@##adLayer mediabistro.com#@##adLeader contracostatimes.com,mercurynews.com#@##adPosition0 mautofied.com,segundamano.es#@##adText sanmarcosrecord.com#@##ad_1 sanmarcosrecord.com#@##ad_2 sanmarcosrecord.com#@##ad_3 sanmarcosrecord.com#@##ad_4 sanmarcosrecord.com#@##ad_5 vgchartz.com#@##ad_728_90 karjalainen.fi#@##ad_area todaystmj4.com#@##ad_banner sexzindian.com#@##ad_center apnaohio.com,syfygames.com#@##ad_content michaels.com#@##ad_header eonline.com#@##ad_leaderboard 9stream.com,seeon.tv,sportlemon.tv#@##ad_overlay neonalley.com,streetinsider.com,vizanime.com#@##ad_space wretch.cc#@##ad_square bestadsontv.com#@##ad_table nbc.com,syfygames.com,theawl.com#@##ad_unit afro-ninja.com#@##ad_wrap adspot.lk,amnestyusa.org,commoncause.org,drownedinsound.com,hardocp.com,prosperityactions.com#@##ad_wrapper livestrong.com#@##adaptv_ad_player_div analogplanet.com,audiostream.com,hometheater.com,innerfidelity.com,shutterbug.com,stereophile.com#@##adbackground homeclick.com#@##adbanner bplaced.net,explosm.net,pocket-lint.com,tweakguides.com#@##adbar adblockplus.org,clipconverter.cc#@##adblock amfiindia.com#@##adbody 2leep.com,landwirt.com,quaintmere.de#@##adbox games.com#@##adcode gamesfreak.net,gifmagic.com,jobs.wa.gov.au,lalovings.com#@##adcontainer about.com,ehow.com#@##adcontainer1 guloggratis.dk#@##adcontent changeofaddressform.com#@##adhead jobs.wa.gov.au#@##adheader choone.com#@##adimg1 popcap.com#@##adlayer adnews.pl#@##adnews contracostatimes.com,insidebayarea.com,mercurynews.com,siliconvalley.com#@##adposition3 gamecopyworld.com,gamecopyworld.eu,morningstar.com#@##adright lifeinvader.com#@##ads-col skelbiu.lt#@##adsHeader mexx.ca#@##ads_bottom gamereactor.dk,gamereactor.es,gamereactor.eu,gamereactor.se#@##ads_right hcplzen.cz,lamag.com#@##ads_top gayexpress.co.nz#@##ads_wrapper videozed.net#@##adsdiv carryconcealed.net,haberler.com,promoce.cz,ps3scenefiles.com,sondakika.com#@##adsense remixshare.com#@##adsense_block jeeppatriot.com#@##adsense_inline autoweek.com,cooperhewitt.org,core77.com,metblogs.com,oreilly.com,thisisthehive.net#@##adspace e24.se#@##adspace_top smh.com.au,theage.com.au#@##adspot-300x250-pos-1 theage.com.au#@##adspot-300x250-pos-2 mautofied.com,thisisads.co.uk#@##adtext 4sysops.com,autogidas.lt,ew.com,globalsecurity.org#@##adtop al.com,cleveland.com,gulflive.com,lehighvalleylive.com,masslive.com,mlive.com,nj.com,nola.com,oregonlive.com,pennlive.com,silive.com,syracuse.com#@##adv-masthead lawinfo.com#@##adv-top inverterbolsa.com#@##advert1 lakeviewfinancial.net#@##advert2 tiv.pw#@##advertisement1 telkomspeedy.com#@##advertisetop govolsxtra.com,legacy.com#@##advertising_wrapper flyroyalbrunei.com#@##adverts tirebusiness.com#@##advtop bionity.com,frumforum.com,windows7gadgets.net#@##adwrapper allieiswired.com,catb.org#@##banner-ad asuragen.com#@##bannerAd visitscotland.com#@##bannerAdWrapper macrumors.com#@##banner_topad alltimesgames.com,go.com,kennedyhealth.org,modernmedicine.com#@##bannerad hotels.mapov.com,redcanoecu.com#@##bigAd sudoku.com.au#@##bigad themediaonline.co.za#@##body_ad freeshipping.com#@##bottomAds unicreatures.com#@##bottom_ad hifi-forsale.co.uk#@##centerads shoryuken.com#@##cmn_ad_tag_head stickam.com#@##companionAd lava360.com#@##content-header-ad arquivo.wiki.br,orientaldaily.on.cc#@##contentAd gamereactor.dk,gamereactor.es,gamereactor.eu,gamereactor.se#@##content_ads tgfcer.com#@##content_adv orientaldaily.on.cc#@##contentad bestbuy.com#@##dart-container-728x90 oxforddictionaries.com#@##dfp_ad_Entry_728x90 oxforddictionaries.com#@##dfp_ad_Home_728x90 israelnationalnews.com,mtanyct.info,presstv.com,presstv.ir#@##divAd chicagotribune.com,latimes.com,puzzles.usatoday.com,washingtonpost.com#@##div_prerollAd_1 epicshare.net#@##download_ad discuss.com.hk,uwants.com#@##featuread clickbd.com#@##featured-ads racingjunk.com#@##featuredAds headlinestoday.intoday.in#@##footer_ad investopedia.com#@##footer_ads adultswim.com#@##game-ad pescorner.net#@##googlead sfexaminer.com#@##gridAdSidebar cozi.com,uwcu.org#@##head-ad fashionmagazine.com#@##header-ads newgrowbook.com#@##headerAd independenttraveler.com#@##headerAdContainer airplaydirect.com,cmt.com,hollywoodoops.com#@##header_ad guysen.com#@##homead aetv.com#@##ka_adRightSkyscraperWide journalrecord.com#@##leaderAd newegg.com#@##leaderBoardAd blogcritics.org#@##leaderboard-ad ratecity.com.au#@##leaderboard-advertisement boattrader.com#@##left-ad eva.vn#@##left_ads briefing.com#@##leftad wyomingnews.com#@##leftads sunnewsnetwork.ca#@##logoAd truecar.com#@##logo_ad wellsfargo.com#@##mainAd straighttalk.com,theloop.com.au#@##main_ad cyclingnews.com#@##mpu2 cyclingnews.com#@##mpu2_container cyclingnews.com#@##mpu_container tei-c.org#@##msad 4kidstv.com#@##myAd 180upload.nl,epicshare.net,lemuploads.com,megarelease.org#@##player_ads govolsxtra.com#@##pre_advertising_wrapper box10.com,chicagotribune.com,enemy.com,flashgames247.com,hackedarcadegames.com,latimes.com,puzzles.usatoday.com,washingtonpost.com#@##prerollAd flickr.com#@##promo-ad dailygames.com#@##publicidad mmgastro.pl#@##reklama smilelocal.com#@##rh-ad eva.vn#@##right_ads repair-home.com#@##right_adsense rollingstone.com#@##search-sponsor gumtree.co.za,gumtree.pl,kijiji.ca#@##searchAd logic-immo.be#@##search_ads spinner.com#@##sideAd japantoday.com#@##side_ads gaelick.com,romstone.net#@##sidebar-ads facebook.com,japantoday.com#@##sidebar_ads allthingsd.com#@##skybox-ad zapak.com#@##sponsorAdDiv marketwatch.com#@##sponsoredlinks members.portalbuzz.com#@##sponsors-home 3dmark.com,yougamers.com#@##takeover_ad foodbeast.com#@##top-ad isource.com#@##topAd playstationlifestyle.net#@##topAdSpace sdtimes.com#@##topAdSpace_div inverterbolsa.com#@##topAdvert neowin.net#@##topBannerAd morningstar.se,zootoo.com#@##top_ad hbwm.com#@##top_ads 72tips.com,bumpshack.com,isource.com,millionairelottery.com,pdrhealth.com,psx-scene.com,stickydillybuns.com#@##topad audiostream.com,foxsports540.com,soundandvision.com#@##topbannerad theblaze.com#@##under_story_ad my-magazine.me,nbc.com,theglobeandmail.com#@##videoAd sudoku.com.au#@#.ADBAR superbikeplanet.com#@#.AdBody:not(body) co-operative.coop,co-operativetravel.co.uk,cooptravel.co.uk#@#.AdBox backpage.com#@#.AdInfo buy.com,superbikeplanet.com#@#.AdTitle home-search.org.uk#@#.AdvertContainer homeads.co.nz#@#.HomeAds travelzoo.com#@#.IM_ad_unit ehow.com#@#.RelatedAds everydayhealth.com#@#.SponsoredContent apartments.com#@#.ad-300x250 optimum.net#@#.ad-banner bash.fm,tbns.com.au#@#.ad-block auctionstealer.com#@#.ad-border members.portalbuzz.com#@#.ad-btn assetbar.com,jazzradio.com,o2.pl#@#.ad-button asiasold.com,bahtsold.com,propertysold.asia#@#.ad-cat small-universe.com#@#.ad-cell jobmail.co.za,odysseyware.com#@#.ad-display foxnews.com,yahoo.com#@#.ad-enabled bigfishaudio.com,dublinairport.com,yahoo.com#@#.ad-holder freebitco.in,recycler.com#@#.ad-img kijiji.ca#@#.ad-inner daanauctions.com,queer.pl#@#.ad-item cnet.com#@#.ad-leader-top businessinsider.com#@#.ad-leaderboard daanauctions.com,jerseyinsight.com#@#.ad-left reformgovernmentsurveillance.com#@#.ad-link guloggratis.dk#@#.ad-links gumtree.com#@#.ad-panel forums.soompi.com#@#.ad-placement jerseyinsight.com#@#.ad-right signatus.eu#@#.ad-section wmagazine.com#@#.ad-served asterisk.org,ifokus.se#@#.ad-sidebar 10tv.com#@#.ad-square speedtest.net#@#.ad-stack jobmail.co.za,junkmail.co.za,version2.dk#@#.ad-text buccaneers.com,dallascowboys.com,jaguars.com,kcchiefs.com,liveside.net,neworleanssaints.com,patriots.com,philadelphiaeagles.com,seahawks.com,steelers.com,sulekha.com,vikings.com,washingtonpost.com#@#.ad-top etonline.com,interscope.com#@#.ad-unit billboard.com#@#.ad-unit-300-wrapper speedtest.net#@#.ad-vertical-container tvlistings.aol.com#@#.ad-wide howtopriest.com,nydailynews.com#@#.ad-wrap citylab.com,dealsonwheels.com,happypancake.com,lifeinvader.com,makers.com#@#.ad-wrapper harpers.org#@#.ad300 parade.com#@#.ad728 interviewmagazine.com#@#.ad90 abcfamily.go.com,livestrong.com,locatetv.com#@#.adBlock aftenposten.no#@#.adBottomBoard expedia.com,ksl.com#@#.adBox amfiindia.com,expressz.hu,gumtree.co.za,hotgamesforgirls.com,mycareer.com.au,quotefx.com#@#.adContent superbikeplanet.com#@#.adDiv contracostatimes.com,insidebayarea.com,mercurynews.com,siliconvalley.com#@#.adElement birdchannel.com,catchannel.com,dogchannel.com,fishchannel.com,horsechannel.com,smallanimalchannel.com,youngrider.com#@#.adFrame interpals.net#@#.adFrameCnt autotrader.co.za#@#.adHead autotrader.co.za,ctv.ca,ctvnews.ca#@#.adHeader ctvbc.ctv.ca#@#.adHeaderblack thebulletinboard.com#@#.adHeadline namesecure.com,superhry.cz#@#.adHolder superhry.cz#@#.adHoldert autotrader.co.za,gumtree.co.nz,gumtree.co.za,gumtree.com,gumtree.com.au,gumtree.ie,gumtree.pl,gumtree.sg,ikea.com,kijiji.ca,ksl.com#@#.adImg ceskatelevize.cz,ct24.cz#@#.adItem greatergood.com,uol.com.br#@#.adLink seznam.cz#@#.adMiddle cheaptickets.com,orbitz.com#@#.adMod outspark.com#@#.adModule hotels.mapov.com#@#.adOverlay advertiser.ie#@#.adPanel shockwave.com#@#.adPod aggeliestanea.gr#@#.adResult pogo.com#@#.adRight is.co.za,smc.edu,ticketsnow.com#@#.adRotator microsoft.com,northjersey.com#@#.adSpace 1520wbzw.com,760kgu.biz,880thebiz.com,ap.org,biz1190.com,business1110ktek.com,kdow.biz,kkol.com,money1055.com,takealot.com#@#.adSpot autotrader.co.za,thebulletinboard.com#@#.adText autotrader.co.za,ksl.com,superbikeplanet.com#@#.adTitle empowher.com#@#.adTopHome streamcloud.eu#@#.adWidget cocktailsoftheworld.com,hotgamesforgirls.com,supersonicads.com#@#.adWrap sanmarcosrecord.com#@#.ad_1 techreport.com#@#.ad_160 courierpostonline.com#@#.ad_160x600 focustaiwan.tw,sanmarcosrecord.com#@#.ad_2 sanmarcosrecord.com#@#.ad_3 elledecor.com,nydailynews.com,tvland.com#@#.ad_728x90 globest.com#@#.ad_960 nirmaltv.com#@#.ad_Right focustaiwan.tw#@#.ad_block panarmenian.net#@#.ad_body go.com#@#.ad_container bebusiness.eu,environmentjob.co.uk,lowcarbonjobs.com,myhouseabroad.com#@#.ad_description 318racing.org,linuxforums.org,modelhorseblab.com#@#.ad_global_header gizmodo.jp,kotaku.jp,lifehacker.jp#@#.ad_head_rectangle horsemart.co.uk,merkatia.com,mysportsclubs.com,news.yahoo.com#@#.ad_header olx.pt,whatuni.com#@#.ad_img bebusiness.eu,myhouseabroad.com,njuskalo.hr,starbuy.sk.data10.websupport.sk#@#.ad_item timesofmalta.com#@#.ad_leaderboard tvrage.com#@#.ad_line yirmidorthaber.com#@#.ad_middle rediff.com#@#.ad_outer tvland.com#@#.ad_promo weather.yahoo.com#@#.ad_slug_table chinapost.com.tw#@#.ad_space huffingtonpost.co.uk#@#.ad_spot bbs.newhua.com,starbuy.sk.data10.websupport.sk#@#.ad_text fastseeksite.com,njuskalo.hr#@#.ad_title oxforddictionaries.com#@#.ad_trick_header oxforddictionaries.com#@#.ad_trick_left wg-gesucht.de#@#.ad_wrap athensmagazine.gr#@#.ad_wrapper citypress.co.za#@#.ad_zone choone.com,usairways.com#@#.adarea espni.go.com,nownews.com,nva.gov.lv#@#.adbanner fifthinternational.org,sudoku.com.au#@#.adbar smilelocal.com#@#.adbottom thelog.com#@#.adbutton lancasteronline.com#@#.adcolumn archiwumallegro.pl#@#.adcont bmwoglasnik.si,completemarkets.com,superbikeplanet.com#@#.addiv linux.com#@#.adframe nick.com#@#.adfree choone.com#@#.adheader northjersey.com,rabota.by#@#.adholder backpage.com#@#.adinfo pcmag.com#@#.adkit insomnia.gr,kingsinteriors.co.uk,superbikeplanet.com#@#.adlink bmwoglasnik.si,clickindia.com#@#.adlist find-your-horse.com#@#.admain smilelocal.com#@#.admiddle tomwans.com#@#.adright skatteverket.se#@#.adrow1 skatteverket.se#@#.adrow2 community.pictavo.com#@#.ads-1 community.pictavo.com#@#.ads-2 community.pictavo.com#@#.ads-3 pch.com#@#.ads-area queer.pl#@#.ads-col burzahrane.hr#@#.ads-header members.portalbuzz.com#@#.ads-holder t3.com#@#.ads-inline celogeek.com,checkrom.com#@#.ads-item bannerist.com#@#.ads-right apple.com#@#.ads-section community.pictavo.com,juicesky.com#@#.ads-title queer.pl#@#.ads-top uploadbaz.com#@#.ads1 jw.org#@#.adsBlock download.cnet.com#@#.ads_catDiv santabanta.com#@#.ads_div shopmos.net#@#.ads_top quebarato.com.br,search.conduit.com#@#.ads_wrapper alluc.org#@#.adsbottombox advancedrenamer.com,epicbundle.com,weightlosereally.com,willyoupressthebutton.com#@#.adsbygoogle copart.com#@#.adscontainer live365.com#@#.adshome chupelupe.com#@#.adside wg-gesucht.de#@#.adslot_blurred 4kidstv.com,banknbt.com,kwik-fit.com,mac-sports.com#@#.adspace cutepdf-editor.com#@#.adtable absolute.com#@#.adtile smilelocal.com#@#.adtop promodj.com#@#.adv300 goal.com#@#.adv_300 pistonheads.com#@#.advert-block eatsy.co.uk#@#.advert-box chycor.co.uk#@#.advert-container pistonheads.com#@#.advert-content mobifrance.com#@#.advert-horizontal horsedeals.com.au#@#.advert-wrapper jamesedition.com#@#.advert2 pdc.tv#@#.advertColumn basingstokehomebid.org.uk,homefindersomerset.co.uk#@#.advertContainer longstonetyres.co.uk#@#.advertLink longstonetyres.co.uk#@#.advertText niedziela.nl#@#.advert_container browsershots.org#@#.advert_list pets4homes.co.uk#@#.advertbox itavisen.no#@#.advertisement-1 zalora.co.id,zalora.co.th,zalora.com.my,zalora.com.ph,zalora.sg#@#.advertisement-block mocpages.com#@#.advertisement-swimlane buyout.pro,news.com.au,zlinked.com#@#.advertiser alusa.org#@#.advertising_block anobii.com#@#.advertisment grist.org#@#.advertorial ransquawk.com,trh.sk#@#.adverts stjornartidindi.is#@#.adverttext staircase.pl#@#.adwords consumerist.com#@#.after-post-ad deluxemusic.tv#@#.article_ad jiji.ng#@#.b-advert annfammed.org#@#.banner-ads plus.net,putlocker.com#@#.banner300 mlb.com#@#.bannerAd milenio.com#@#.banner_728x90 mergermarket.com#@#.banner_ad cumbooks.co.za,eurweb.com,infoplease.com#@#.bannerad popporn.com,webphunu.net#@#.block-ad diena.lt#@#.block-simpleads oliveoiltimes.com#@#.blog-ads hispanicbusiness.com#@#.bottom-ad newagestore.com#@#.bottom-ads nytimes.com#@#.bottom-left-ad 123poi.com#@#.bottomAds ixbtlabs.com#@#.bottom_ad_block queer.pl#@#.box-ads wired.com#@#.box-radvert theonion.com#@#.boxad weather.yahoo.com#@#.can_ad_slug deployhappiness.com,dmitrysotnikov.wordpress.com,faravirusi.com#@#.category-ad gegenstroemung.org#@#.change_AdContainer findicons.com,tattoodonkey.com#@#.container_ad insidefights.com#@#.container_row_ad theology.edu#@#.contentAd verizonwireless.com#@#.contentAds freevoipdeal.com,voipstunt.com#@#.content_ads glo.msn.com#@#.cp-adsInited gottabemobile.com#@#.custom-ad theweek.com#@#.desktop-ad dn.se#@#.displayAd deviantart.com#@#.download_ad boattrader.com#@#.featured-ad racingjunk.com#@#.featuredAdBox webphunu.net#@#.flash-advertisement songlyrics.com#@#.footer-ad employmentguide.com#@#.footer-ads koopik.com#@#.footerad ebayclassifieds.com,guloggratis.dk#@#.gallery-ad time.com#@#.google-sponsored gumtree.co.za#@#.googleAdSense nicovideo.jp#@#.googleAds waer.org#@#.has-ad assetbar.com,burningangel.com,donthatethegeek.com,intomobile.com,thenationonlineng.net,wccftech.com#@#.header-ad greenbayphoenix.com,photobucket.com#@#.headerAd dailytimes.com.pk,swns.com#@#.header_ad associatedcontent.com#@#.header_ad_center kidzworld.com#@#.header_advert plugcomputer.org#@#.headerad haaretz.com#@#.headerads gnc.co.uk,iedrc.org#@#.home-ad kazg1440.com,theworldwidewolf.com#@#.home-ads heals.co.uk,questapartments.com.au#@#.homeAd worldsnooker.com#@#.homead gq.com#@#.homepage-ad straighttalk.com#@#.homepage_ads radaronline.com#@#.horizontal_ad bodas.com.mx,bodas.net,mariages.net,matrimonio.com,weddingspot.co.uk#@#.img_ad a-k.tel,baldai.tel,boracay.tel,covarrubias.tel#@#.imgad lespac.com#@#.inner_ad classifiedads.com#@#.innerad forbes.com#@#.interstitial_ad_wrapper silveradoss.com#@#.ipsAd magazines-download.com#@#.item-ads amazinglytimedphotos.com#@#.item-container-ad everybodysucksbutus.com,usatoday.com#@#.leaderboard-ad ajcn.org,annfammed.org#@#.leaderboard-ads lolhit.com#@#.leftAd lolhit.com#@#.leftad ebayclassifieds.com#@#.list-ad asiasold.com,bahtsold.com,comodoroenventa.com,propertysold.asia#@#.list-ads euspert.com#@#.listad ap.org,atea.com,ateadirect.com,knowyourmobile.com#@#.logo-ad eagleboys.com.au#@#.marketing-ad driverscollection.com#@#.mid_ad donga.com#@#.middle_AD latimes.com#@#.mod-adopenx thenewamerican.com#@#.module-ad ziehl-abegg.com#@#.newsAd dn.se#@#.oasad antronio.com,frogueros.com#@#.openx adn.com,wiktionary.org#@#.page-ad rottentomatoes.com#@#.page_ad bachofen.ch#@#.pfAd iitv.info#@#.player_ad putlocker.com,vodu.ch#@#.player_hover_ad latimes.com#@#.pm-ad bigfootpage.com,gumtree.com#@#.post-ad venturebeat.com#@#.post-sponsored ayosdito.ph,christianhouseshare.com.au,trovit.pl#@#.post_ad personalpost.washingtonpost.com#@#.post_ads freeads.co.uk,gumtree.co.za,sahibinden.com#@#.postad wesh.com#@#.premiumAdOverlay wesh.com#@#.premiumAdOverlayClose timeoutbengaluru.net,timeoutdelhi.net,timeoutmumbai.net#@#.promoAd 4-72.com.co,bancainternet.com.ar,frogueros.com,northwestfm.co.za,tushop.com.ar,vukanifm.org,wrlr.fm,zibonelefm.co.za#@#.publicidad ebay.co.uk,theweek.com#@#.pushdown-ad engadget.com#@#.rail-ad interpals.net#@#.rbRectAd collegecandy.com#@#.rectangle_ad salon.com#@#.refreshAds foreignaffairs.com#@#.region-top-ad-position uploadic.com#@#.reklam doradcy24.pl,mmgastro.pl,offmoto.com,slovaknhl.sk#@#.reklama tradera.com#@#.reportAdLink 7-eleven.com#@#.right-ad theberrics.com,weddingchannel.com#@#.rightAd post-gazette.com#@#.right_ad dailymotion.com#@#.right_ads_column theberrics.com,w3schools.com,x17online.com#@#.rightad tobarandualchais.co.uk#@#.rightadv webtoolhub.com#@#.sb_adsNv2 gumtree.co.za#@#.searchAds mail.yahoo.com#@#.searchad avizo.cz,bisexual.com#@#.searchads arbetsformedlingen.se,wunderground.com#@#.showAd agelioforos.gr,domainrural.com.au#@#.side-ad suntimes.com#@#.side-bar-ad-position1 adspot.lk,recycler.com#@#.single-ad myaccount.nytimes.com#@#.singleAd cbsnews.com#@#.skinAd radaronline.com#@#.sky_ad comicbookmovie.com#@#.skyscraperAd reuters.com#@#.slide-ad caarewards.ca#@#.smallAd boylesports.com#@#.small_ad hebdenbridge.co.uk,store.gameshark.com#@#.smallads theforecaster.net#@#.sponsor-box xhamster.com#@#.sponsorBottom getprice.com.au#@#.sponsoredLinks golfmanagerlive.com#@#.sponsorlink giantlife.com,hellobeautiful.com,newsone.com,theurbandaily.com#@#.sticky-ad kanui.com.br,nytimes.com#@#.text-ad kingsofchaos.com#@#.textad antronio.com,cdf.cl,frogueros.com#@#.textads anythinghollywood.com,aylak.com#@#.top-ad programmableweb.com#@#.top-ad-wrapper nypress.com,timescall.com#@#.topAds horsemart.co.uk,torrentv.org#@#.top_ad conversations.nokia.com#@#.top_ad_div egmnow.com#@#.top_ad_wrap imagepicsa.com,sun.mv,trailvoy.com#@#.top_ads earlyamerica.com,infojobs.net#@#.topads nfl.com#@#.tower-ad yahoo.com#@#.type_ads_default vinden.se#@#.view_ad nytimes.com#@#.wideAd britannica.com,cam4.com#@#.withAds theuspatriot.com#@#.wpInsertInPostAd weather.yahoo.com#@#.yom-ad bitrebels.com#@#a[href*="/adrotate-out.php?"] santander.co.uk#@#a[href^="http://ad-emea.doubleclick.net/"] jabong.com,people.com,techrepublic.com,time.com#@#a[href^="http://ad.doubleclick.net/"] watchever.de#@#a[href^="http://adfarm.mediaplex.com/"] betbeaver.com,betwonga.com#@#a[href^="http://ads.betfair.com/redirect.aspx?"] betwonga.com#@#a[href^="http://ads2.williamhill.com/redirect.aspx?"] betwonga.com#@#a[href^="http://adserving.unibet.com/"] adultfriendfinder.com#@#a[href^="http://adultfriendfinder.com/p/register.cgi?pid="] betwonga.com#@#a[href^="http://affiliate.coral.co.uk/processing/"] marketgid.com,mgid.com#@#a[href^="http://marketgid.com"] marketgid.com,mgid.com#@#a[href^="http://mgid.com/"] betwonga.com#@#a[href^="http://online.ladbrokes.com/promoRedirect?"] linkedin.com,tasteofhome.com#@#a[href^="http://pubads.g.doubleclick.net/"] marketgid.com,mgid.com#@#a[href^="http://us.marketgid.com"] betbeaver.com,betwonga.com#@#a[href^="http://www.bet365.com/home/?affiliate"] fbooksluts.com#@#a[href^="http://www.fbooksluts.com/"] fleshjack.com,fleshlight.com#@#a[href^="http://www.fleshlight.com/"] www.google.com#@#a[href^="http://www.google.com/aclk?"] google.ca,google.co.nz,google.co.uk,google.com,google.com.au,google.de#@#a[href^="http://www.liutilities.com/"] socialsex.com#@#a[href^="http://www.socialsex.com/"] fuckbookhookups.com#@#a[href^="http://www.yourfuckbook.com/?"] marketgid.com,mgid.com#@#a[id^="mg_add"] marketgid.com,mgid.com#@#div[id^="MarketGid"] beqala.com,drupalcommerce.org,ensonhaber.com,eurweb.com,faceyourmanga.com,isc2.org,liverc.com,mit.edu,peekyou.com,podomatic.com,virginaustralia.com,wlj.net,zavvi.com#@#div[id^="div-gpt-ad-"] bodas.com.mx,bodas.net,mariages.net,matrimonio.com,weddingspot.co.uk#@#iframe[id^="google_ads_frame"] bodas.com.mx,bodas.net,mariages.net,matrimonio.com,weddingspot.co.uk#@#iframe[id^="google_ads_iframe"] weather.yahoo.com#@#iframe[src^="http://ad.yieldmanager.com/"] ! Anti-Adblock incredibox.com,litecoiner.net#@##ad-bottom incredibox.com#@##ad-header litecoiner.net#@##ad-right bitcoiner.net,litecoiner.net#@##ad-top zeez.tv#@##ad_overlay cnet.com#@##adboard olweb.tv#@##ads1 gooprize.com,jsnetwork.fr#@##ads_bottom unixmen.com#@##adsense spoilertv.com#@##adsensewide 8muses.com#@##adtop anisearch.com,lilfile.com#@##advertise yafud.pl#@##bottomAd dizi-mag.com#@##header_ad thesimsresource.com#@##leaderboardad linkshrink.net#@##overlay_ad exashare.com#@##player_ads iphone-tv.eu#@##sidebar_ad freebitcoins.nx.tc,getbitcoins.nx.tc#@##sponsorText dailybitcoins.org#@#.ad-img uptobox.com#@#.ad-leader uptobox.com#@#.ad-square afreesms.com#@#.adbanner apkmirror.com#@#.adsWidget afreesms.com#@#.adsbox afreesms.com,anonymousemail.me,anonymousemail.us,bitcoin-faucet.eu,btcinfame.com,classic-retro-games.com,coingamez.com,doulci.net,eveskunk.com,filecore.co.nz,freebitco.in,get-bitcoin-free.eu,gnomio.com,incredibox.com,mangacap.com,mangakaka.com,niresh.co,nzb.su,r1db.com,spoilertv.com,unlocktheinbox.com,zeperfs.com#@#.adsbygoogle afreesms.com#@#.adspace browsershots.org#@#.advert_area velasridaura.com#@#.advertising_block guitarforum.co.za,tf2r.com#@#.adverts cheatpain.com,directwonen.nl,dramacafe.in,eveskunk.com,exashare.com,farsondigitalwatercams.com,file4go.com,freeccnaworkbook.com,gaybeeg.info,hack-sat.com,keygames.com,latesthackingnews.com,localeyes.dk,manga2u.co,mangasky.co,minecraftskins.com,moneyinpjs.com,online.dramacafe.tv,ps3news.com,psarips.com,thenewboston.com,tubitv.com#@#.afs_ads coindigger.biz#@#.banner160x600 anisearch.com#@#.chitikaAdBlock theladbible.com#@#.content_tagsAdTech topzone.lt#@#.forumAd linkshrink.net#@#.overlay_ad localeyes.dk#@#.pub_300x250 localeyes.dk#@#.pub_300x250m localeyes.dk#@#.pub_728x90 localeyes.dk#@#.text-ad localeyes.dk#@#.text-ad-links localeyes.dk#@#.text-ads localeyes.dk#@#.textAd localeyes.dk#@#.text_ad incredibox.com,localeyes.dk,turkanime.tv,videopremium.tv#@#.text_ads menstennisforums.com#@#.top_ads coingamez.com,mangaumaru.com,milfzr.com,pencurimovie.cc#@#div[id^="div-gpt-ad-"] afreesms.com#@#iframe[id^="google_ads_frame"] !---------------------------Third-party advertisers---------------------------! ! *** easylist:easylist/easylist_adservers.txt *** ||007-gateway.com^$third-party ||0icep80f.com^$third-party ||101m3.com^$third-party ||103092804.com^$third-party ||10fbb07a4b0.se^$third-party ||10pipsaffiliates.com^$third-party ||1100i.com^$third-party ||123date.me^$third-party ||152media.com^$third-party ||15f3c01a.info^$third-party ||15f3c01c.info^$third-party ||174.142.194.177^$third-party ||17a898b9.info^$third-party ||17a898bb.info^$third-party ||188.138.1.45^$third-party,domain=~shatecraft.com.ip ||188server.com^$third-party ||18clicks.com^$third-party ||194.71.107.25^$third-party ||199.102.225.178^$third-party,domain=~adsimilate.ip ||1clickdownloads.com^$third-party ||1phads.com^$third-party ||1sadx.net^$third-party ||1yk851od.com^$third-party ||204.93.181.78^$third-party,domain=~discountmags.ip ||206ads.com^$third-party ||209.222.8.217^$third-party,domain=~p2p.adserver.ip ||20dollars2surf.com^$third-party ||213.163.70.183^$third-party ||247realmedia.com^$third-party ||254a.com^$third-party ||2d4c3870.info^$third-party ||2d4c3872.info^$third-party ||2dpt.com^$third-party ||2mdn.net/dot.gif$object-subrequest,third-party ||2mdn.net^$object-subrequest,third-party,domain=101cargames.com|1025thebull.com|1031iheartaustin.com|1037theq.com|1041beat.com|1053kissfm.com|1057ezrock.com|1067litefm.com|10news.com|1310news.com|247comedy.com|3news.co.nz|49ers.com|610cktb.com|680news.com|700wlw.com|850koa.com|923jackfm.com|92q.com|940winz.com|94hjy.com|970espn.com|99kisscountry.com|abc15.com|abc2news.com|abcactionnews.com|am1300thezone.com|am570radio.com|am760.net|ap.org|atlantafalcons.com|automobilemag.com|automotive.com|azcardinals.com|baltimoreravens.com|baynews9.com|bbc.co.uk|bbc.com|belfasttelegraph.co.uk|bengals.com|bet.com|big1059.com|bigdog1009.ca|bloomberg.com|bnn.ca|boom92houston.com|boom945.com|boom973.com|boom997.com|boomphilly.com|box10.com|brisbanetimes.com.au|buccaneers.com|buffalobills.com|bullz-eye.com|businessweek.com|calgaryherald.com|caller.com|canada.com|capitalfm.ca|cbsnews.com|cbssports.com|channel955.com|chargers.com|chez106.com|chfi.com|chicagobears.com|chicagotribune.com|cj104.com|cjad.com|cjbk.com|clevelandbrowns.com|cnettv.cnet.com|coast933.com|colts.com|commercialappeal.com|country1011.com|country1043.com|country1067.com|country600.com|courierpress.com|cp24.com|cricketcountry.com|csmonitor.com|ctvnews.ca|dallascowboys.com|denverbroncos.com|detroitlions.com|drive.com.au|earthcam.com|edmontonjournal.com|egirlgames.net|elvisduran.com|enjoydressup.com|entrepreneur.com|eonline.com|escapegames.com|euronews.com|evolution935.com|fansportslive.com|fm98wjlb.com|foodnetwork.ca|four.co.nz|foxradio.ca|foxsportsradio.com|fresh100.com|gamingbolt.com|ghananation.com|giantbomb.com|giants.com|globalpost.com|globaltoronto.com|globaltv.com|globaltvbc.com|globaltvcalgary.com|go.com|gorillanation.com|gosanangelo.com|hallelujah1051.com|hellobeautiful.com|heraldsun.com.au|hgtv.ca|hiphopnc.com|hot1041stl.com|hotair.com|hothiphopdetroit.com|hotspotatl.com|houstontexans.com|ibtimes.co.uk|iheart.com|independent.ie|independentmail.com|indyhiphop.com|ipowerrichmond.com|jackfm.ca|jaguars.com|kase101.com|kcchiefs.com|kcci.com|kcra.com|kdvr.com|kfiam640.com|kgbx.com|khow.com|kiisfm.com|kiss925.com|kissnorthbay.com|kisssoo.com|kisstimmins.com|kitsapsun.com|kitv.com|kjrh.com|kmov.com|knoxnews.com|kogo.com|komonews.com|kshb.com|kwgn.com|kwnr.com|kxan.com|kysdc.com|latinchat.com|leaderpost.com|livestream.com|local8now.com|magic96.com|majorleaguegaming.com|metacafe.com|miamidolphins.com|mix923fm.com|mojointhemorning.com|moneycontrol.com|montrealgazette.com|motorcyclistonline.com|mtv.ca|myboom1029.com|mycolumbusmagic.com|mycolumbuspower.com|myezrock.com|mymagic97.com|naplesnews.com|nationalpost.com|nba.com|nba.tv|ndtv.com|neworleanssaints.com|news1130.com|newsinc.com|newsmax.com|newsmaxhealth.com|newsnet5.com|newsone.com|newstalk1010.com|newstalk1130.com|newyorkjets.com|nydailynews.com|nymag.com|oktvusa.com|oldschoolcincy.com|ottawacitizen.com|packers.com|panthers.com|patriots.com|pcworld.com|philadelphiaeagles.com|player.screenwavemedia.com|prowrestling.com|q92timmins.com|raaga.com|radio.com|radionowindy.com|raiders.com|rapbasement.com|redding.com|redskins.com|reporternews.com|reuters.com|rollingstone.com|rootsports.com|rottentomatoes.com|seahawks.com|sherdog.com|skynews.com.au|slice.ca|smh.com.au|sploder.com|sportsnet590.ca|sportsnet960.ca|steelers.com|stlouisrams.com|streetfire.net|stuff.co.nz|tcpalm.com|telegraph.co.uk|theage.com.au|theaustralian.com.au|thebeatdfw.com|theboxhouston.com|thedenverchannel.com|thedrocks.com|theindychannel.com|theprovince.com|thestarphoenix.com|theteam1260.com|tide.com|timescolonist.com|timeslive.co.za|timesrecordnews.com|titansonline.com|totaljerkface.com|townhall.com|tripadvisor.ca|tripadvisor.co.id|tripadvisor.co.uk|tripadvisor.com|tripadvisor.com.au|tripadvisor.com.my|tripadvisor.com.sg|tripadvisor.ie|tripadvisor.in|turnto23.com|tvone.tv|tvoneonline.com|twitch.tv|twitchy.com|usmagazine.com|vancouversun.com|vcstar.com|veetle.com|vice.com|videojug.com|vikings.com|virginradio.ca|vzaar.com|wapt.com|washingtonpost.com|washingtontimes.com|wcpo.com|wdfn.com|weather.com|wescfm.com|wgci.com|wibw.com|wikihow.com|windsorstar.com|wiod.com|wiznation.com|wjdx.com|wkyt.com|wmyi.com|wor710.com|wptv.com|wsj.com|wxyz.com|wyff4.com|yahoo.com|youtube.com|z100.com|zhiphopcleveland.com ||2mdn.net^$~object-subrequest,third-party ||2xbpub.com^$third-party ||32b4oilo.com^$third-party ||3393.com^$third-party ||350media.com^$third-party ||360ads.com^$third-party ||360yield.com^$third-party ||365sbaffiliates.com^$third-party ||3cnce854.com^$third-party ||3lift.com^$third-party ||3lr67y45.com^$third-party ||3omb.com^$third-party ||3rdads.com^$third-party ||3redlightfix.com^$third-party ||3t7euflv.com^$third-party ||43plc.com^$third-party ||46.165.197.153^ ||46.165.197.231^ ||46.246.120.230^$third-party,domain=~adexprt.com.ip ||4affiliate.net^$third-party ||4dsply.com^$third-party ||4e43ac9c.info^$third-party ||4uvjosuc.com^$third-party ||4wnet.com^$third-party ||50.7.243.123^$third-party ||5362367e.info^$third-party ||5clickcashsoftware.com^$third-party ||5gl1x9qc.com^$third-party ||600z.com^$third-party ||62.27.51.163^$third-party,domain=~adlive.de.ip ||63.225.61.4^$third-party ||64.20.60.123^$third-party ||74.117.182.77^ ||777seo.com^$third-party ||78.138.126.253^$third-party ||78.140.131.214^ ||7insight.com^$third-party ||7search.com^$third-party ||7u8a8i88.com^$third-party ||82d914.se^$third-party ||87.230.102.24^$third-party,domain=~p2p.adserver.ip ||888media.net^$third-party ||888medianetwork.com^$third-party ||888promos.com^$third-party ||8yxupue8.com^$third-party ||97d73lsi.com^$third-party ||9ts3tpia.com^$third-party ||a-ads.com^$third-party ||a-static.com^$third-party ||a.raasnet.com^$third-party ||a2dfp.net^$third-party ||a2pub.com^$third-party ||a3pub.com^$third-party ||a433.com^$third-party ||a4dtrk.com^$third-party ||a5pub.com^$third-party ||aa.voice2page.com^$third-party ||aaa.at4.info^$third-party ||aaa.dv0.info^$third-party ||abletomeet.com^$third-party ||abnad.net^$third-party ||aboutads.quantcast.com^$third-party ||abtracker.us^$third-party ||accelacomm.com^$third-party ||access-mc.com^$third-party ||accmgr.com^$third-party ||accounts.pkr.com^$third-party ||accuserveadsystem.com^$third-party ||acf-webmaster.net^$third-party ||acronym.com^$third-party ||actiondesk.com^$third-party ||activedancer.com^$third-party ||ad-back.net^$third-party ||ad-balancer.net^$third-party ||ad-bay.com^$third-party ||ad-clicks.com^$third-party ||ad-delivery.net^$third-party ||ad-flow.com^$third-party ||ad-gbn.com^$third-party ||ad-indicator.com^$third-party ||ad-m.asia^$third-party ||ad-maven.com^$third-party ||ad-media.org^$third-party ||ad-server.co.za^$third-party ||ad-serverparc.nl^$third-party ||ad-sponsor.com^$third-party ||ad-srv.net^$third-party ||ad-stir.com^$third-party ||ad-vice.biz^$third-party ||ad.atdmt.com/i/a.html$third-party ||ad.atdmt.com/i/a.js$third-party ||ad.doubleclick.net^$~object-subrequest,third-party ||ad.mo.doubleclick.net/dartproxy/$third-party ||ad.yieldpartners.com^$third-party ||ad120m.com^$third-party ||ad121m.com^$third-party ||ad122m.com^$third-party ||ad123m.com^$third-party ||ad125m.com^$third-party ||ad127m.com^$third-party ||ad128m.com^$third-party ||ad129m.com^$third-party ||ad131m.com^$third-party ||ad132m.com^$third-party ||ad134m.com^$third-party ||ad20.net^$third-party ||ad2387.com^$third-party ||ad2adnetwork.biz^$third-party ||ad2games.com^$third-party,domain=~jobvite.com ||ad2up.com^$third-party ||ad4game.com^$third-party ||ad6media.fr^$third-party ||adacado.com^$third-party ||adaction.se^$third-party ||adadvisor.net^$third-party ||adagora.com^$third-party ||adaos-ads.net^$third-party ||adap.tv^$~object-subrequest,third-party ||adapd.com^$third-party ||adbard.net^$third-party ||adbasket.net^$third-party ||adblade.com^$third-party ||adboost.com^$third-party ||adbooth.net^$third-party ||adbrau.com^$third-party ||adbrite.com^$third-party ||adbroo.com^$third-party ||adbull.com^$third-party ||adbureau.net^$third-party ||adbutler.com^$third-party ||adbuyer.com^$third-party ||adcade.com^$third-party ||adcash.com^$third-party ||adcastplus.net^$third-party ||adcde.com^$third-party ||adcdnx.com^$third-party ||adcentriconline.com^$third-party ||adcfrthyo.tk^$third-party ||adchap.com^$third-party ||adchemical.com^$third-party ||adchoice.co.za^$third-party ||adclick.lv^$third-party ||adclick.pk^$third-party ||adclickafrica.com^$third-party ||adclickmedia.com^$third-party ||adcloud.net^$third-party ||adcolo.com^$third-party ||adcount.in^$third-party ||adcron.com^$third-party ||adcru.com^$third-party ||addaim.com^$third-party ||addelive.com^$third-party ||addiply.com^$third-party ||addoer.com^$third-party ||addroid.com^$third-party ||addynamics.eu^$third-party ||addynamix.com^$third-party ||addynamo.net^$third-party ||adecn.com^$third-party ||adedy.com^$third-party ||adelement.com^$third-party ||ademails.com^$third-party ||adengage.com^$third-party ||adespresso.com^$third-party ||adexcite.com^$third-party ||adexprt.com^$third-party ||adexprts.com^$third-party ||adextent.com^$third-party ||adf01.net^$third-party ||adfactory88.com^$third-party ||adfeedstrk.com^$third-party ||adfootprints.com^$third-party ||adforgames.com^$third-party ||adforgeinc.com^$third-party ||adform.net^$third-party ||adframesrc.com^$third-party ||adfrika.com^$third-party ||adfrog.info^$third-party ||adfrontiers.com^$third-party ||adfunkyserver.com^$third-party ||adfusion.com^$third-party ||adgalax.com^$third-party ||adgardener.com^$third-party ||adgatemedia.com^$third-party ||adgear.com^$third-party ||adgebra.co.in^$third-party ||adgent007.com^$third-party ||adgila.com^$third-party ||adgine.net^$third-party ||adgitize.com^$third-party ||adglamour.net^$third-party ||adgorithms.com^$third-party ||adgoto.com^$third-party ||adgroups.com^$third-party ||adgrx.com^$third-party ||adhese.be^$third-party ||adhese.com^$third-party ||adhese.net^$third-party ||adhitzads.com^$third-party ||adhostingsolutions.com^$third-party ||adhub.co.nz^$third-party ||adicate.com^$third-party ||adigniter.org^$third-party ||adimise.com^$third-party ||adimpact.com^$third-party ||adimperia.com^$third-party ||adimpression.net^$third-party ||adinch.com^$third-party ||adincon.com^$third-party ||adindigo.com^$third-party ||adinfinity.com.au^$third-party ||adinterax.com^$third-party ||adip.ly^$third-party ||adiqglobal.com^$third-party ||adireland.com^$third-party ||adisfy.com^$third-party ||adisn.com^$third-party ||adition.com^$third-party ||adjal.com^$third-party ||adjector.com^$third-party ||adjug.com^$third-party ||adjuggler.com^$third-party ||adjuggler.net^$third-party ||adjungle.com^$third-party ||adk2.co^$third-party ||adk2.com^$third-party ||adkengage.com^$third-party ||adkick.net^$third-party ||adklip.com^$third-party ||adknowledge.com^$third-party ||adkonekt.com^$third-party ||adlayer.net^$third-party ||adlegend.com^$third-party ||adlink.net^$third-party ||adlinx.info^$third-party ||adlisher.com^$third-party ||adloaded.com^$third-party ||adlooxtracking.com^$third-party ||adlure.biz^$third-party ||adlux.com^$third-party ||adm.fwmrm.net/crossdomain.xml$domain=cc.com|mtv.com ||adm.fwmrm.net/p/msnbc_live/$object-subrequest,third-party,domain=~msnbc.msn.com|~www.nbcnews.com ||adm.fwmrm.net/p/mtvn_live/$object-subrequest,third-party ||admagnet.net^$third-party ||admailtiser.com^$third-party ||admamba.com^$third-party ||adman.gr^$third-party ||admanage.com^$third-party ||admarketplace.net^$third-party ||admaxim.com^$third-party ||admaya.in^$third-party ||admedia.com^$third-party ||admedias.net^$third-party ||admeld.com^$third-party ||admeta.com^$third-party ||admission.net^$third-party ||admitad.com^$third-party ||admixer.net^$third-party ||admngronline.com^$third-party ||admpads.com^$third-party ||admulti.com^$third-party ||admzn.com^$third-party ||adne.tv^$third-party ||adnectar.com^$third-party ||adnet-media.net^$third-party ||adnet.biz^$third-party ||adnet.com^$third-party ||adnet.de^$third-party ||adnet.lt^$third-party ||adnet.ru^$third-party ||adnet.vn^$third-party ||adnetworkme.com^$third-party ||adnext.fr^$third-party ||adngin.com^$third-party ||adnimation.com^$third-party ||adnoble.com^$third-party ||adnxs.com^$third-party ||adnxs.net^$third-party ||adnxs1.com^$third-party ||adocean.pl^$third-party ||adonion.com^$third-party ||adonly.com^$third-party ||adonweb.ru^$third-party ||adoperator.com^$third-party ||adoptim.com^$third-party ||adorika.com^$third-party ||adorika.net^$third-party ||adotic.com^$third-party ||adotomy.com^$third-party ||adotube.com^$third-party ||adpacks.com^$third-party ||adparlor.com^$third-party ||adpath.mobi^$third-party ||adpay.com^$third-party ||adperfect.com^$third-party ||adperium.com^$third-party ||adphreak.com^$third-party ||adpinion.com^$third-party ||adpionier.de^$third-party ||adplans.info^$third-party ||adplxmd.com^$third-party ||adppv.com^$third-party ||adpremo.com^$third-party ||adprofit2share.com^$third-party ||adproper.info^$third-party ||adprotected.com^$third-party ||adprovi.de^$third-party ||adprs.net^$third-party ||adquest3d.com^$third-party ||adready.com^$third-party ||adreadytractions.com^$third-party ||adresellers.com^$third-party ||adrevolver.com^$third-party ||adrich.cash^$third-party ||adrise.de^$third-party ||adrocket.com^$third-party ||adroll.com^$third-party ||ads-elsevier.net^$third-party ||ads-stats.com^$third-party ||ads01.com^$third-party ||ads2ads.net^$third-party ||ads2srv.com^$third-party ||ads4cheap.com^$third-party ||adsafeprotected.com^$third-party ||adsalvo.com^$third-party ||adsame.com^$third-party ||adsbookie.com^$third-party ||adsbrook.com^$third-party ||adscale.de^$third-party ||adscampaign.net^$third-party ||adscendmedia.com^$third-party ||adsclickingnetwork.com^$third-party ||adsdk.com^$third-party ||adsdot.ph^$third-party ||adsensecamp.com^$third-party ||adserv8.com^$third-party ||adserve.com^$third-party ||adserve.ph^$third-party ||adserver-fx.com^$third-party ||adserverplus.com^$third-party ||adserverpub.com^$third-party ||adservinginternational.com^$third-party ||adservpi.com^$third-party ||adservr.de^$third-party ||adsfac.eu^$third-party ||adsfac.net^$third-party ||adsfac.us^$third-party ||adsfactor.net^$third-party ||adsfast.com^$third-party ||adsforindians.com^$third-party ||adsfundi.com^$third-party ||adsfundi.net^$third-party ||adsfuse.com^$third-party ||adshack.com^$third-party ||adshexa.com^$third-party ||adshopping.com^$third-party ||adshost1.com^$third-party ||adshost2.com^$third-party ||adshot.de^$third-party ||adshuffle.com^$third-party ||adsignals.com^$third-party ||adsimilis.com^$third-party ||adsinimages.com^$third-party ||adskeeper.co.uk^$third-party ||adslidango.com^$third-party ||adslingers.com^$third-party ||adslot.com^$third-party ||adsmarket.com^$third-party ||adsmarket.es^$third-party ||adsmedia.cc^$third-party ||adsmile.biz^$third-party ||adsmoon.com^$third-party ||adsmws.cloudapp.net^$third-party ||adsnative.com^$third-party ||adsnext.net^$third-party ||adsniper.ru^$third-party ||adsonar.com^$third-party ||adsopx.com^$third-party ||adsovo.com^$third-party ||adspaper.org^$third-party ||adspdbl.com^$third-party ||adspeed.com^$third-party ||adspirit.de^$third-party ||adspring.to^$third-party ||adspruce.com^$third-party ||adspynet.com^$third-party ||adsrevenue.net^$third-party ||adsring.com^$third-party ||adsrv.us^$third-party ||adsrvmedia.com^$third-party ||adsrvmedia.net^$third-party ||adsrvr.org^$third-party ||adssites.net^$third-party ||adstatic.com^$third-party ||adsummos.net^$third-party ||adsupermarket.com^$third-party ||adsupply.com^$third-party ||adsurve.com^$third-party ||adsvert.com^$third-party ||adswizz.com^$third-party ||adsxgm.com^$third-party ||adsymptotic.com^$third-party ||adtaily.com^$third-party ||adtaily.eu^$third-party ||adtaily.pl^$third-party ||adtdp.com^$third-party ||adtecc.com^$third-party ||adtech.de^$third-party ||adtechus.com^$third-party ||adtegrity.net^$third-party ||adteractive.com^$third-party ||adtgs.com^$third-party ||adtlgc.com^$third-party ||adtoadd.com^$third-party ||adtoll.com^$third-party ||adtology1.com^$third-party ||adtology2.com^$third-party ||adtology3.com^$third-party ||adtoma.com^$third-party ||adtomafusion.com^$third-party ||adtoox.com^$third-party ||adtotal.pl^$third-party ||adtpix.com^$third-party ||adtrace.org^$third-party ||adtransfer.net^$third-party ||adtrgt.com^$third-party ||adtrix.com^$third-party ||adtrovert.com^$third-party ||adtruism.com^$third-party ||adtwirl.com^$third-party ||aduacni.com^$third-party ||adult-adv.com^$third-party ||adultadworld.com^$third-party ||adultimate.net^$third-party ||adulttds.com^$third-party ||adurr.com^$third-party ||adv-adserver.com^$third-party ||adv9.net^$third-party ||advanseads.com^$third-party ||advantageglobalmarketing.com^$third-party ||advard.com^$third-party ||advatar.to^$third-party ||adventori.com^$third-party ||adversal.com^$third-party ||adversaldisplay.com^$third-party ||adversalservers.com^$third-party ||adverserve.net^$third-party ||advertarium.com.ua^$third-party ||advertbox.us^$third-party ||adverteerdirect.nl^$third-party ||adverticum.net^$third-party ||advertise.com^$third-party ||advertiseforfree.co.za^$third-party ||advertisegame.com^$third-party ||advertisespace.com^$third-party ||advertiseyourgame.com^$third-party ||advertising-department.com^$third-party ||advertising.com^$third-party ||advertising365.com^$third-party ||advertisingiq.com^$third-party ||advertisingpath.net^$third-party ||advertisingvalue.info^$third-party ||advertjunction.com^$third-party ||advertlead.net^$third-party ||advertlets.com^$third-party ||advertmarketing.com^$third-party ||advertmedias.com^$third-party ||advertpay.net^$third-party ||advertrev.com^$third-party ||advertserve.com^$third-party ||advertstatic.com^$third-party ||advertstream.com^$third-party ||advertur.ru^$third-party ||advertxi.com^$third-party ||advg.jp^$third-party ||advgoogle.com^$third-party ||adviva.net^$third-party ||advmd.com^$third-party ||advmedialtd.com^$third-party ||advombat.ru^$third-party ||advpoints.com^$third-party ||advrtice.com^$third-party ||advsnx.net^$third-party ||adwires.com^$third-party ||adwordsservicapi.com^$third-party ||adworkmedia.com^$third-party ||adworldmedia.com^$third-party ||adworldmedia.net^$third-party ||adxcore.com^$third-party ||adxion.com^$third-party ||adxpose.com^$third-party ||adxpower.com^$third-party ||adyoulike.com^$third-party ||adyoz.com^$third-party ||adz.co.zw^$third-party ||adzerk.net^$third-party ||adzhub.com^$third-party ||adzonk.com^$third-party ||adzouk.com^$third-party ||adzs.nl^$third-party ||afcyhf.com^$third-party ||afdads.com^$third-party ||aff.biz^$third-party ||affbot1.com^$third-party ||affbot3.com^$third-party ||affbot7.com^$third-party ||affbot8.com^$third-party ||affbuzzads.com^$third-party ||affec.tv^$third-party ||affiliate-b.com^$third-party ||affiliate-gate.com^$third-party ||affiliate-robot.com^$third-party ||affiliate.com^$third-party ||affiliate.cx^$third-party ||affiliatebannerfarm.com^$third-party ||affiliateedge.com^$third-party ||affiliateer.com^$third-party ||affiliatefuel.com^$third-party ||affiliatefuture.com^$third-party ||affiliategateways.co^$third-party ||affiliategroove.com^$third-party ||affiliatelounge.com^$third-party ||affiliatemembership.com^$third-party ||affiliatesensor.com^$third-party ||affiliation-france.com^$third-party ||affiliationcash.com^$third-party ||affiliationworld.com^$third-party ||affiliationzone.com^$third-party ||affilijack.de^$third-party ||affiliproducts.com^$third-party ||affiliserve.com^$third-party ||affimo.de^$third-party ||affinitad.com^$third-party ||affinity.com^$third-party ||affiz.net^$third-party ||affplanet.com^$third-party ||afftrack.com^$third-party ||aflrm.com^$third-party ||africawin.com^$third-party ||afterdownload.com^$third-party ||afterdownloads.com^$third-party ||afy11.net^$third-party ||agcdn.com^$third-party ||agentcenters.com^$third-party ||aggregateknowledge.com^$third-party ||aglocobanners.com^$third-party ||agmtrk.com^$third-party ||agvzvwof.com^$third-party ||aim4media.com^$third-party ||aimatch.com^$third-party ||ajansreklam.net^$third-party ||alchemysocial.com^$third-party ||alfynetwork.com^$third-party ||alimama.com^$third-party ||allabc.com^$third-party ||alleliteads.com^$third-party ||allmt.com^$third-party ||alloydigital.com^$third-party ||allyes.com^$third-party ||alphabird.com^$third-party ||alphabirdnetwork.com^$third-party ||alphagodaddy.com^$third-party ||alternads.info^$third-party ||alternativeadverts.com^$third-party ||altitude-arena.com^$third-party ||am-display.com^$third-party ||am10.ru^$third-party ||am11.ru^$third-party ||am15.net^$third-party ||amazon-adsystem.com^$third-party ||amazon-cornerstone.com^$third-party ||amazonily.com^$third-party ||amertazy.com^$third-party ||amgdgt.com^$third-party ||ampxchange.com^$third-party ||anastasiasaffiliate.com^$third-party ||andohs.net^$third-party ||andomedia.com^$third-party ||andomediagroup.com^$third-party ||angege.com^$third-party ||anonymousads.com^$third-party ||anrdoezrs.net^$third-party ||anwufkjjja.com^$third-party ||anymedia.lv^$third-party ||anyxp.com^$third-party ||aoqneyvmaz.com^$third-party ||aorms.com^$third-party ||aorpum.com^$third-party ||apex-ad.com^$third-party ||apmebf.com^$third-party ||appendad.com^$third-party ||applebarq.com^$third-party ||apptap.com^$third-party ||april29-disp-download.com^$third-party ||apsmediaagency.com^$third-party ||apxlv.com^$third-party ||arab4eg.com^$third-party ||arabweb.biz^$third-party ||arcadebannerexchange.net^$third-party ||arcadebannerexchange.org^$third-party ||arcadebanners.com^$third-party ||arcadebe.com^$third-party ||arcadechain.com^$third-party ||areasnap.com^$third-party ||arti-mediagroup.com^$third-party ||as5000.com^$third-party ||asafesite.com^$third-party ||aseadnet.com^$third-party ||asklots.com^$third-party ||asooda.com^$third-party ||asrety.com^$third-party ||assetize.com^$third-party ||assoc-amazon.ca^$third-party ||assoc-amazon.co.uk^$third-party ||assoc-amazon.com^$third-party ||assoc-amazon.de^$third-party ||assoc-amazon.es^$third-party ||assoc-amazon.fr^$third-party ||assoc-amazon.it^$third-party ||asterpix.com^$third-party ||astree.be^$third-party ||atemda.com^$third-party ||atmalinks.com^$third-party ||ato.mx^$third-party ||atomex.net^$third-party ||atrinsic.com^$third-party ||atwola.com^$third-party ||au2m8.com^$third-party ||auctionnudge.com^$third-party ||audience2media.com^$third-party ||audiencefuel.com^$third-party ||audienceprofiler.com^$third-party ||auditude.com^$third-party ||aunmdhxrco.com^$third-party ||auspipe.com^$third-party ||auto-im.com^$third-party ||auto-insurance-quotes-compare.com^$third-party ||automatedtraffic.com^$third-party ||automateyourlist.com^$third-party ||avads.co.uk^$third-party ||avalanchers.com^$third-party ||avazu.net^$third-party ||avazutracking.net^$third-party ||avercarto.com^$third-party ||awaps.net^$third-party ||awempire.com^$third-party ||awin1.com^$third-party ||awltovhc.com^$third-party ||awsmer.com^$third-party ||awsurveys.com^$third-party ||axill.com^$third-party ||ayboll.com^$third-party ||azads.com^$third-party ||azjmp.com^$third-party ||azoogleads.com^$third-party ||azorbe.com^$third-party ||b117f8da23446a91387efea0e428392a.pl^$third-party ||b6508157d.website^$third-party ||babbnrs.com^$third-party ||backbeatmedia.com^$third-party ||backlinks.com^$third-party ||badjocks.com^$third-party ||baldiro.de^$third-party ||bananaflippy.com^$third-party ||banner-clix.com^$third-party ||banner-rotation.com^$third-party ||bannerbank.ru^$third-party ||bannerblasters.com^$third-party ||bannerbridge.net^$third-party ||bannercde.com^$third-party ||bannerconnect.com^$third-party ||bannerconnect.net^$third-party ||bannerdealer.com^$third-party ||bannerexchange.com.au^$third-party ||bannerflow.com^$third-party ||bannerflux.com^$third-party ||bannerignition.co.za^$third-party ||bannerjammers.com^$third-party ||bannerlot.com^$third-party ||bannerperformance.net^$third-party ||bannerrage.com^$third-party ||bannersmania.com^$third-party ||bannersnack.com^$third-party ||bannersnack.net^$third-party ||bannersurvey.biz^$third-party ||bannertgt.com^$third-party ||bannertracker-script.com^$third-party ||bannerweb.com^$third-party ||baronsoffers.com^$third-party ||bbelements.com^$third-party ||beaconads.com^$third-party ||beatchucknorris.com^$third-party ||beead.co.uk^$third-party ||beead.net^$third-party ||beforescence.com^$third-party ||begun.ru^$third-party ||belointeractive.com^$third-party ||belvertising.be^$third-party ||bentdownload.com^$third-party ||bepolite.eu^$third-party ||beringmedia.com^$third-party ||bestcasinopartner.com^$third-party ||bestdeals.ws^$third-party ||bestfindsite.com^$third-party ||bestforexpartners.com^$third-party ||bestgameads.com^$third-party ||besthitsnow.com^$third-party ||bestofferdirect.com^$third-party ||bestonlinecoupons.com^$third-party ||bet3000partners.com^$third-party ||bet365affiliates.com^$third-party ||betaffs.com^$third-party ||betrad.com^$third-party ||bettingpartners.com^$third-party ||bfast.com^$third-party ||bh3.net^$third-party ||bidgewatr.com^$third-party ||bidsystem.com^$third-party ||bidvertiser.com^$third-party ||biemedia.com^$third-party ||bigadpoint.net^$third-party ||bigfineads.com^$third-party ||bijscode.com^$third-party ||bimlocal.com^$third-party ||bin-layer.de^$third-party ||bin-layer.ru^$third-party ||binaryoptionssystems.org^$third-party ||bingo4affiliates.com^$third-party ||binlayer.com^$third-party ||binlayer.de^$third-party ||bitads.net^$third-party ||bitcoinadvertisers.com^$third-party ||bitfalcon.tv^$third-party ||bittads.com^$third-party ||bitx.tv^$third-party ||bizographics.com^$third-party ||bizrotator.com^$third-party ||bizzclick.com^$third-party ||blamads.com^$third-party ||blamcity.com^$third-party ||blardenso.com^$third-party ||blinkadr.com^$third-party ||blogads.com^$third-party ||blogbannerexchange.com^$third-party ||blogclans.com^$third-party ||bloggerex.com^$third-party ||blogherads.com^$third-party ||blogohertz.com^$third-party ||blueadvertise.com^$third-party ||bluestreak.com^$third-party ||blumi.to^$third-party ||bmanpn.com^$third-party ||bnetworx.com^$third-party ||bnmla.com^$third-party ||bnr.sys.lv^$third-party ||bogads.com^$third-party ||bonusfapturbo.com^$third-party ||boo-box.com^$third-party ||booklandonline.info^$third-party ||boostclic.com^$third-party ||bormoni.ru^$third-party ||bororas.com^$third-party ||boydadvertising.co.uk^$third-party ||boylesportsreklame.com^$third-party ||bptracking.com^$third-party ||br.rk.com^$third-party ||brainient.com^$third-party ||branchr.com^$third-party ||brand-display.com^$third-party ||brand.net^$third-party ||brandaffinity.net^$third-party ||brandclik.com^$third-party ||brandreachsys.com^$third-party ||bravenetmedianetwork.com^$third-party ||breadpro.com^$third-party ||brealtime.com^$third-party ||bridgetrack.com^$third-party ||brighteroption.com^$third-party ||brightshare.com^$third-party ||broadstreetads.com^$third-party ||brucelead.com^$third-party ||bstrtb.com^$third-party ||btnibbler.com^$third-party ||btrll.com^$third-party ||bttbgroup.com^$third-party ||bu520.com^$third-party ||bubblesmedia.ru^$third-party ||bucketsofbanners.com^$third-party ||budurl.com^$third-party ||buildtrafficx.com^$third-party ||bunchofads.com^$third-party ||bunny-net.com^$third-party ||burbanked.info^$third-party ||burjam.com^$third-party ||burnsoftware.info^$third-party ||burstnet.com^$third-party ||businesscare.com^$third-party ||businessclick.com^$third-party ||busterzaster.de^$third-party ||buxflow.com^$third-party ||buxp.org^$third-party ||buyflood.com^$third-party ||buyorselltnhomes.com^$third-party ||buysellads.com^$third-party ||buzzcity.net^$third-party ||buzzparadise.com^$third-party ||bwinpartypartners.com^$third-party ||byspot.com^$third-party ||byzoo.org^$third-party ||c-on-text.com^$third-party ||c-planet.net^$third-party ||c8.net.ua^$third-party ||camleyads.info^$third-party ||campanja.com^$third-party ||canoeklix.com^$third-party ||capacitygrid.com^$third-party ||capitatmarket.com^$third-party ||captainad.com^$third-party ||captifymedia.com^$third-party ||carambo.la^$third-party ||carbonads.com^$third-party ||carrier.bz^$third-party ||cartorkins.com^$third-party ||casalemedia.com^$third-party ||cash-duck.com^$third-party ||cash4members.com^$third-party ||cashatgsc.com^$third-party ||cashmylinks.com^$third-party ||cashonvisit.com^$third-party ||cashtrafic.com^$third-party ||cashtrafic.info^$third-party ||cashworld.biz^$third-party ||caspion.com^$third-party ||casterpretic.com^$third-party ||castplatform.com^$third-party ||caygh.com^$third-party ||cb-content.com^$third-party ||cbaazars.com^$third-party ||cbclickbank.com^$third-party ||cbclicks.com^$third-party ||cbleads.com^$third-party ||cbn.tbn.ru^$third-party ||cc-dt.com^$third-party ||cdn-image.com^$third-party ||cdn.mobicow.com^$third-party ||cdna.tremormedia.com^$third-party ||cdnads.com^$third-party ||cdnrl.com^$third-party ||cdnservr.com^$third-party ||centralnervous.net^$third-party ||cerotop.com^$third-party ||cgecwm.org^$third-party ||chango.com^$third-party ||chanished.net^$third-party ||charltonmedia.com^$third-party ||checkm8.com^$third-party ||checkmystats.com.au^$third-party ||checkoutfree.com^$third-party ||cherytso.com^$third-party ||chicbuy.info^$third-party ||china-netwave.com^$third-party ||chinagrad.ru^$third-party ||chipleader.com^$third-party ||chitika.com^$third-party ||chitika.net^$third-party ||chronicads.com^$third-party ||cibleclick.com^$third-party ||city-ads.de^$third-party ||citysite.net^$third-party ||cjt1.net^$third-party ||clarityray.com^$third-party ||clash-media.com^$third-party ||claxonmedia.com^$third-party ||clayaim.com^$third-party ||cleafs.com^$third-party ||clear-request.com^$third-party ||clente.com^$third-party ||clevv.com^$third-party ||click.scour.com^$third-party ||click2jump.com^$third-party ||click4free.info^$third-party ||clickable.com^$third-party ||clickad.pl^$third-party ||clickagy.com^$third-party ||clickbet88.com^$third-party ||clickbooth.com^$third-party ||clickboothlnk.com^$third-party ||clickbubbles.net^$third-party ||clickcash.com^$third-party ||clickcertain.com^$third-party ||clickequations.net^$third-party ||clickexa.com^$third-party ||clickexperts.net^$third-party ||clickfuse.com^$third-party ||clickintext.com^$third-party ||clickintext.net^$third-party ||clickkingdom.net^$third-party ||clickmyads.info^$third-party ||clicknano.com^$third-party ||clickosmedia.com^$third-party ||clicks2count.com^$third-party ||clicksor.com^$third-party ||clicksor.net^$third-party ||clicksurvey.mobi^$third-party ||clickthrucash.com^$third-party ||clicktripz.com^$third-party ||clickupto.com^$third-party ||clickwinks.com^$third-party ||clickxchange.com^$third-party ||clixgalore.com^$third-party ||clixsense.com^$third-party ||clixtrac.com^$third-party ||clkrev.com^ ||clnk.me^$third-party ||cltomedia.info^$third-party ||clz3.net^$third-party ||cmfads.com^$third-party ||cmllk1.info^$third-party ||cnt.my^$third-party ||cntdy.mobi^$third-party ||coadvertise.com^$third-party ||codezap.com^$third-party ||codigobarras.net^$third-party ||coedmediagroup.com^$third-party ||cogocast.net^$third-party ||cogsdigital.com^$third-party ||coguan.com^$third-party ||coinadvert.net^$third-party ||collection-day.com^$third-party ||collective-media.net^$third-party ||colliersads.com^$third-party ||comclick.com^$third-party ||commission-junction.com^$third-party ||commission.bz^$third-party ||commissionfactory.com.au^$third-party ||commissionlounge.com^$third-party ||commissionmonster.com^$third-party ||completecarrd.com^$third-party ||comscore.com^$third-party ||conduit-banners.com^$third-party ||connatix.com^$third-party ||connectedads.net^$third-party ||connectionads.com^$third-party ||connexity.net^$third-party ||connexplace.com^$third-party ||connextra.com^$third-party ||construment.com^$third-party ||consumergenepool.com^$third-party ||contadd.com^$third-party ||contaxe.com^$third-party ||content-cooperation.com^$third-party ||content.ad^$third-party ||contentclick.co.uk^$third-party ||contentdigital.info^$third-party ||contenture.com^$third-party ||contentwidgets.net^$third-party ||contexlink.se^$third-party ||contextads.net^$third-party ||contextuads.com^$third-party ||contextweb.com^$third-party ||coolerads.com^$third-party ||coolmirage.com^$third-party ||copacet.com^$third-party ||coretarget.co.uk^$third-party ||cornflip.com^$third-party ||coull.com^$third-party ||coupon2buy.com^$third-party ||covertarget.com^*_*.php ||cpabeyond.com^$third-party ||cpaclicks.com^$third-party ||cpaclickz.com^$third-party ||cpagrip.com^$third-party ||cpalead.com^$third-party ||cpalock.com^$third-party ||cpanuk.com^$third-party ||cpaway.com^$third-party ||cpays.com^$third-party ||cpcadnet.com^$third-party ||cpfclassifieds.com^$third-party ||cpm.biz^$third-party ||cpmadvisors.com^$third-party ||cpmaffiliation.com^$third-party ||cpmleader.com^$third-party ||cpmmedia.net^$third-party ||cpmrocket.com^$third-party ||cpmstar.com^$third-party ||cpmtree.com^$third-party ||cpuim.com^$third-party ||cpulaptop.com^$third-party ||cpvads.com^$third-party ||cpvadvertise.com^$third-party ||cpvmarketplace.info^$third-party ||cpvtgt.com^$third-party ||cpx24.com^$third-party ||cpxadroit.com^$third-party ||cpxinteractive.com^$third-party ||crakmedia.com^$third-party ||crazylead.com^$third-party ||crazyvideosempire.com^$third-party ||creative-serving.com^$third-party ||creditcards15x.tk^$third-party ||crispads.com^$third-party ||criteo.com^$third-party ||criteo.net^$third-party ||crossrider.com^$third-party ||crowdgatheradnetwork.com^$third-party ||crowdgravity.com^$third-party ||cruiseworldinc.com^$third-party ||ctasnet.com^$third-party ||ctm-media.com^$third-party ||ctrhub.com^$third-party ||cubics.com^$third-party ||cuelinks.com^$third-party ||curancience.com^$third-party ||currentlyobsessed.me^$third-party ||curtisfrierson.com^$third-party ||cybmas.com^$third-party ||cygnus.com^$third-party ||d.m3.net^$third-party ||d03x2011.com^$third-party ||d1110e4.se^$third-party ||d2ship.com^$third-party ||da-ads.com^$third-party ||dadegid.ru^$third-party ||danitabedtick.net^$third-party ||dapper.net^$third-party ||darwarvid.com^$third-party ||dashboardad.net^$third-party ||dating-banners.com^$third-party ||datinggold.com^$third-party ||dbbsrv.com^$third-party ||dbclix.com^$third-party ||dealcurrent.com^$third-party ||decisionmark.com^$third-party ||decisionnews.com^$third-party ||decknetwork.net^$third-party ||dedicatedmedia.com^$third-party ||dedicatednetworks.com^$third-party ||deepmetrix.com^$third-party ||defaultimg.com^$third-party ||deguiste.com^$third-party ||dehtale.ru^$third-party ||delivery45.com^$third-party ||delivery47.com^$third-party ||delivery49.com^$third-party ||delivery51.com^$third-party ||deplayer.net^$third-party ||deployads.com^$third-party ||derlatas.com^$third-party ||destinationurl.com^$third-party ||detroposal.com^$third-party ||developermedia.com^$third-party ||deximedia.com^$third-party ||dexplatform.com^$third-party ||dgmatix.com^$third-party ||dgmaustralia.com^$third-party ||dgmaxinteractive.com^$third-party ||dhundora.com^$third-party ||diamondtraff.com^$third-party ||dianomioffers.co.uk^$third-party ||digipathmedia.com^$third-party ||digitrevenue.com^$third-party ||dinclinx.com^$third-party ||dipads.net^$~image,third-party ||directaclick.com^$third-party ||directile.info^$third-party ||directile.net^$third-party ||directleads.com^$third-party ||directoral.info^$third-party ||directorym.com^$third-party ||directrev.com^$third-party ||directtrack.com^$third-party ||dispop.com^$third-party ||districtm.ca^$third-party ||dl-rms.com^$third-party ||dmu20vut.com^$third-party ||dntrck.com^$third-party ||dollarade.com^$third-party ||dollarsponsor.com^$third-party ||domainadvertising.com^$third-party ||domainbuyingservices.com^$third-party ||domainsponsor.com^$third-party ||domdex.com^$third-party ||doogleonduty.com^$third-party ||dorenga.com^$third-party ||dotandad.com^$third-party ||dotomi.com^$third-party ||double.net^$third-party ||doubleclick.com^$third-party ||doubleclick.net/*/ch_news.com/$third-party ||doubleclick.net/*/pfadx/lin.$third-party ||doubleclick.net/ad/$third-party ||doubleclick.net/adi/$~object-subrequest,third-party ||doubleclick.net/adj/$~object-subrequest,third-party ||doubleclick.net/adj/*.collegehumor/sec=videos_originalcontent;$third-party ||doubleclick.net/adx/$~object-subrequest,third-party ||doubleclick.net/adx/*.collegehumor/$third-party ||doubleclick.net/adx/*.NPR.MUSIC/$third-party ||doubleclick.net/adx/*.NPR/$third-party ||doubleclick.net/adx/*.ted/$third-party ||doubleclick.net/adx/CBS.$third-party ||doubleclick.net/adx/ibs.$third-party ||doubleclick.net/adx/tsg.$third-party ||doubleclick.net/adx/wn.loc.$third-party ||doubleclick.net/adx/wn.nat.$third-party ||doubleclick.net/crossdomain.xml$object-subrequest,domain=abcnews.go.com ||doubleclick.net/N2/pfadx/video.*.wsj.com/$third-party ||doubleclick.net/N2/pfadx/video.allthingsd.com/$third-party ||doubleclick.net/N2/pfadx/video.marketwatch.com/ ||doubleclick.net/N2/pfadx/video.wsj.com/$third-party ||doubleclick.net/N3626/pfadx/thehothits.com.au/$third-party ||doubleclick.net/N4117/pfadx/*.sbs.com.au/$third-party ||doubleclick.net/N4526/pfadx/*.muzu/$third-party ||doubleclick.net/N5202/pfadx/cmn_livemixtapes/$third-party ||doubleclick.net/N5479/pfadx/ctv.$third-party ||doubleclick.net/N6088/pfadx/ssp.kshb/$third-party ||doubleclick.net/N6872/pfadx/shaw.mylifetimetv.ca/$third-party ||doubleclick.net/pfadx/*.ABC.com/$third-party ||doubleclick.net/pfadx/*.BLIPTV/$third-party ||doubleclick.net/pfadx/*.ESPN/$third-party ||doubleclick.net/pfadx/*.MCNONLINE/$third-party ||doubleclick.net/pfadx/*.MTV-Viacom/$third-party ||doubleclick.net/pfadx/*.mtvi$third-party ||doubleclick.net/pfadx/*.muzu/$third-party ||doubleclick.net/pfadx/*.nbc.com/$third-party ||doubleclick.net/pfadx/*.NBCUNI.COM/$third-party ||doubleclick.net/pfadx/*.NBCUNIVERSAL-CNBC/$third-party ||doubleclick.net/pfadx/*.NBCUNIVERSAL/$third-party ||doubleclick.net/pfadx/*.reuters/$third-party ||doubleclick.net/pfadx/*.sevenload.com_$third-party ||doubleclick.net/pfadx/*.VIACOMINTERNATIONAL/$third-party ||doubleclick.net/pfadx/*.WALTDISNEYINTERNETGROU/$third-party ||doubleclick.net/pfadx/*/kidstv/$third-party ||doubleclick.net/pfadx/*adcat=$third-party ||doubleclick.net/pfadx/*CBSINTERACTIVE/$third-party ||doubleclick.net/pfadx/aetn.aetv.shows/$third-party ||doubleclick.net/pfadx/belo.king5.pre/$third-party ||doubleclick.net/pfadx/bet.com/$third-party ||doubleclick.net/pfadx/blp.video/midroll$third-party ||doubleclick.net/pfadx/bzj.bizjournals/$third-party ||doubleclick.net/pfadx/cblvsn.nwsd.videogallery/$third-party ||doubleclick.net/pfadx/CBS.$third-party ||doubleclick.net/pfadx/ccr.$third-party ||doubleclick.net/pfadx/comedycentral.$third-party ||doubleclick.net/pfadx/csn.$third-party ||doubleclick.net/pfadx/ctv.ctvwatch.ca/$third-party ||doubleclick.net/pfadx/ctv.muchmusic.com/$third-party ||doubleclick.net/pfadx/ctv.spacecast/$third-party ||doubleclick.net/pfadx/ddm.ksl/$third-party ||doubleclick.net/pfadx/gn.movieweb.com/$third-party ||doubleclick.net/pfadx/intl.sps.com/$third-party ||doubleclick.net/pfadx/ltv.wtvr.video/$third-party ||doubleclick.net/pfadx/mc.channelnewsasia.com^$third-party ||doubleclick.net/pfadx/miniclip.midvideo/$third-party ||doubleclick.net/pfadx/miniclip.prevideo/$third-party ||doubleclick.net/pfadx/muzumain/$third-party ||doubleclick.net/pfadx/muzuoffsite/$third-party ||doubleclick.net/pfadx/nbcu.nbc/$third-party ||doubleclick.net/pfadx/nbcu.nhl.$third-party ||doubleclick.net/pfadx/nbcu.nhl/$third-party ||doubleclick.net/pfadx/ndm.tcm/$third-party ||doubleclick.net/pfadx/nfl.$third-party ||doubleclick.net/pfadx/ng.videoplayer/$third-party ||doubleclick.net/pfadx/ssp.kgtv/$third-party ||doubleclick.net/pfadx/storm.no/$third-party ||doubleclick.net/pfadx/sugar.poptv/$third-party ||doubleclick.net/pfadx/tmg.telegraph.$third-party ||doubleclick.net/pfadx/tmz.video.wb.dart/$third-party ||doubleclick.net/pfadx/trb.$third-party ||doubleclick.net/pfadx/ugo.gv.1up/$third-party ||doubleclick.net/pfadx/video.marketwatch.com/$third-party ||doubleclick.net/pfadx/video.wsj.com/$third-party ||doubleclick.net/pfadx/www.tv3.co.nz$third-party ||doubleclick.net^$third-party,domain=3news.co.nz|92q.com|abc-7.com|addictinggames.com|allbusiness.com|allthingsd.com|bizjournals.com|bloomberg.com|bnn.ca|boom92houston.com|boom945.com|boomphilly.com|break.com|cbc.ca|cbs19.tv|cbs3springfield.com|cbsatlanta.com|cbslocal.com|complex.com|dailymail.co.uk|darkhorizons.com|doubleviking.com|euronews.com|extratv.com|fandango.com|fox19.com|fox5vegas.com|gorillanation.com|hawaiinewsnow.com|hellobeautiful.com|hiphopnc.com|hot1041stl.com|hothiphopdetroit.com|hotspotatl.com|hulu.com|imdb.com|indiatimes.com|indyhiphop.com|ipowerrichmond.com|joblo.com|kcra.com|kctv5.com|ketv.com|koat.com|koco.com|kolotv.com|kpho.com|kptv.com|ksat.com|ksbw.com|ksfy.com|ksl.com|kypost.com|kysdc.com|live5news.com|livestation.com|livestream.com|metro.us|metronews.ca|miamiherald.com|my9nj.com|myboom1029.com|mycolumbusmagic.com|mycolumbuspower.com|myfoxdetroit.com|myfoxorlando.com|myfoxphilly.com|myfoxphoenix.com|myfoxtampabay.com|nbcrightnow.com|neatorama.com|necn.com|neopets.com|news.com.au|news4jax.com|newsone.com|nintendoeverything.com|oldschoolcincy.com|own3d.tv|pagesuite-professional.co.uk|pandora.com|player.theplatform.com|ps3news.com|radio.com|radionowindy.com|rottentomatoes.com|sbsun.com|shacknews.com|sk-gaming.com|ted.com|thebeatdfw.com|theboxhouston.com|theglobeandmail.com|timesnow.tv|tv2.no|twitch.tv|universalsports.com|ustream.tv|wapt.com|washingtonpost.com|wate.com|wbaltv.com|wcvb.com|wdrb.com|wdsu.com|wflx.com|wfmz.com|wfsb.com|wgal.com|whdh.com|wired.com|wisn.com|wiznation.com|wlky.com|wlns.com|wlwt.com|wmur.com|wnem.com|wowt.com|wral.com|wsj.com|wsmv.com|wsvn.com|wtae.com|wthr.com|wxii12.com|wyff4.com|yahoo.com|youtube.com|zhiphopcleveland.com ||doubleclick.net^*/ad/$~object-subrequest,third-party ||doubleclick.net^*/adi/$~object-subrequest,third-party ||doubleclick.net^*/adj/$~object-subrequest,third-party ||doubleclick.net^*/pfadx/cmn_complextv/$third-party ||doubleclick.net^*/pfadx/embed.ytpwatch.$third-party ||doubleclick.net^*/pfadx/ibs.orl.news/$third-party ||doubleclick.net^*/pfadx/muzumain/$third-party ||doubleclick.net^*/pfadx/ssp.wews/$third-party ||doubleclick.net^*/pfadx/team.dal/$third-party ||doubleclick.net^*/pfadx/team.sd/$third-party ||doubleclick.net^*;afv_flvurl=http://cdn.c.ooyala.com/$third-party ||doubleclicks.me^$third-party ||doublemax.net^$third-party ||doublepimp.com^$third-party ||doublerads.com^$third-party ||doublerecall.com^$third-party ||doubleverify.com^$third-party ||down1oads.com^$third-party ||downsonglyrics.com^$third-party ||dp25.kr^$third-party ||dpbolvw.net^$third-party ||dpmsrv.com^$third-party ||dpsrexor.com^$third-party ||dpstack.com^$third-party ||dreamaquarium.com^$third-party ||dreamsearch.or.kr^$third-party ||drowle.com^$third-party ||dsero.net^$third-party ||dsnextgen.com^$third-party ||dsnr-affiliates.com^$third-party ||dsultra.com^$third-party ||dt00.net^$third-party,domain=~marketgid.com|~marketgid.ru|~marketgid.ua|~mgid.com|~thechive.com ||dt07.net^$third-party,domain=~marketgid.com|~marketgid.ru|~marketgid.ua|~mgid.com|~thechive.com ||dtmpub.com^$third-party ||dtzads.com^$third-party ||dualmarket.info^$third-party ||dudelsa.com^$third-party ||duetads.com^$third-party ||dumedia.ru^$third-party ||durnowar.com^$third-party ||durtz.com^$third-party ||dvaminusodin.net^$third-party ||dyino.com^$third-party ||dynamicoxygen.com^$third-party ||dynamitedata.com^$third-party ||e-find.co^$third-party ||e-generator.com^$third-party ||e-planning.net^$third-party ||e-viral.com^$third-party ||e9mlrvy1.com^$third-party ||eads-adserving.com^$third-party ||eads.to^$third-party ||easy-adserver.com^$third-party ||easyad.com^$third-party ||easydownload4you.com^$third-party ||easyflirt-partners.biz^$third-party ||easyhits4u.com^$third-party ||easyinline.com^$third-party ||ebannertraffic.com^$third-party ||ebayobjects.com.au^$third-party ||ebayobjects.com^$third-party ||eblastengine.com^$third-party ||ebuzzing.com^$third-party ||ebz.io^$third-party ||edgeads.org^$third-party ||edgevertise.com^$third-party ||edomz.net^$third-party ||eedr.org^$third-party ||effectivemeasure.net^$third-party ||egamingonline.com^$third-party ||ekmas.com^$third-party ||ektezis.ru^$third-party ||elasticad.net^$third-party ||electnext.com^$third-party ||elefantsearch.com^$third-party ||elvate.net^$third-party ||emberads.com^$third-party ||emediate.ch^$third-party ||emediate.dk^$third-party ||emediate.eu^$third-party ||emediate.se^$third-party ||emjcd.com^$third-party ||empiremoney.com^$third-party ||employers-freshly.org^$third-party ||emptyspaceads.com^$third-party ||engineseeker.com^$third-party ||enlnks.com^$third-party ||enterads.com^$third-party ||entrecard.com^$third-party ||entrecard.s3.amazonaws.com^$third-party ||epicgameads.com^$third-party ||epnredirect.ru^$third-party ||eptord.com^$third-party ||eptum.com^$third-party ||erado.org^$third-party ||erendri.com^$third-party ||ergerww.net^$third-party ||ergodob.ru^$third-party ||ero-advertising.com^$third-party ||erovation.com^$third-party ||erovinmo.com^$third-party ||escalatenetwork.com^$third-party ||escale.to^$third-party ||especifican.com^$third-party ||essayads.com^$third-party ||essaycoupons.com^$third-party ||etargetnet.com^$third-party ||etgdta.com^$third-party ||etmanly.ru^$third-party ||etology.com^$third-party ||eurew.com^$third-party ||euroclick.com^$third-party ||europacash.com^$third-party ||euros4click.de^$third-party ||evolvenation.com^$third-party ||exactdrive.com^$third-party ||excellenceads.com^$third-party ||exchange4media.com^$third-party ||exitexplosion.com^$third-party ||exitjunction.com^$third-party ||exoclick.com^$third-party ||exponential.com^$third-party ||expresswebtraffic.com^$third-party ||extra33.com^$third-party ||eyere.com^$third-party ||eyereturn.com^$third-party ||eyeviewads.com^$third-party ||eyewond.hs.llnwd.net^$third-party ||eyewonder.com^$third-party ||ezadserver.net^$third-party ||ezmob.com^$third-party ||ezoic.net^$third-party ||fairadsnetwork.com^$third-party ||falkag.net^$third-party ||fast2earn.com^$third-party ||fastapi.net^$third-party ||fastates.net^$third-party ||fastclick.net^$third-party ||fasttracktech.biz^$third-party ||fb-plus.com^$third-party ||fbgdc.com^$third-party ||fbsvu.com^$third-party ||featuredusers.com^$third-party ||featurelink.com^$third-party ||feed-ads.com^$third-party ||feljack.com^$third-party ||fenixm.com^$third-party ||fidel.to^$third-party ||filetarget.com^$third-party ||filtermomosearch.com^$third-party ||fimserve.com^$third-party ||find-abc.com^$third-party ||find-cheap-hotels.org^$third-party ||findbestsolution.net^$third-party ||findsthat.com^$third-party ||firaxtech.com^$third-party ||firefeeder.com^$third-party ||firegob.com^$third-party ||firmharborlinked.com^$third-party ||first-rate.com^$third-party ||firstadsolution.com^$third-party ||firstimpression.io^$third-party ||firstlightera.com^$third-party ||fixionmedia.com^$third-party ||fl-ads.com^$third-party ||flagads.net^$third-party ||flashclicks.com^$third-party ||flashtalking.com^$third-party ||fliionos.co.uk^$third-party ||flite.com^$third-party ||fllwert.net^$third-party ||flodonas.com^$third-party ||fluidads.co^$third-party ||fluxads.com^$third-party ||flyertown.ca^$third-party ||flymyads.com^$third-party ||fmpub.net^$third-party ||fmsads.com^$third-party ||focalex.com^$third-party ||foodieblogroll.com^$third-party ||foonad.com^$third-party ||footar.com^$third-party ||footerslideupad.com^$third-party ||footnote.com^$third-party ||forced-lose.de^$third-party ||forex-affiliate.com^$third-party ||forex-affiliate.net^$third-party ||forexyard.com^$third-party ||forifiha.com^$third-party ||forpyke.com^$third-party ||forrestersurveys.com^$third-party ||frameptp.com^$third-party ||freebannerswap.co.uk^$third-party ||freebiesurveys.com^$third-party ||freecouponbiz.com^$third-party ||freedownloadsoft.net^$third-party ||freepaidsurveyz.com^$third-party ||freerotator.com^$third-party ||freeskreen.com^$third-party ||freesoftwarelive.com^$third-party ||friendlyduck.com^$third-party ||fruitkings.com^$third-party ||ftjcfx.com^$third-party ||ftv-publicite.fr^$third-party ||fulltraffic.net^$third-party ||funklicks.com^$third-party ||fusionads.net^$third-party ||futureresiduals.com^$third-party ||futureus.com^$third-party ||fwmrm.net^$~object-subrequest,third-party ||fxdepo.com^$third-party ||fxyc0dwa.com^$third-party ||g-cash.biz^$third-party ||g4whisperermedia.com^$third-party ||gagacon.com^$third-party ||gagenez.com^$third-party ||gainmoneyfast.com^$third-party ||galleyn.com^$third-party ||gambling-affiliation.com^$third-party ||game-advertising-online.com^$third-party ||game-clicks.com^$third-party ||gameads.com^$third-party ||gamecetera.com^$third-party ||gamehotus.com^$third-party ||gamersad.com^$third-party ||gamersbanner.com^$third-party ||gamesbannerexchange.com^$third-party ||gamesrevenue.com^$third-party ||gan.doubleclick.net^$third-party ||gandrad.org^$third-party ||gannett.gcion.com^$third-party ||garristo.com^$third-party ||garvmedia.com^$third-party ||gate-ru.com^$third-party ||gatikus.com^$third-party ||gayadnetwork.com^$third-party ||geek2us.net^$third-party ||gefhasio.com^$third-party ||geld-internet-verdienen.net^$third-party ||gemineering.com^$third-party ||genericlink.com^$third-party ||genericsteps.com^$third-party ||genesismedia.com^$third-party ||genovesetacet.com^$third-party ||geo-idm.fr^$third-party ||geoipads.com^$third-party ||geopromos.com^$third-party ||geovisite.com^$third-party ||gestionpub.com^$third-party ||getgamers.eu^$third-party ||getgscfree.com^$third-party ||getscorecash.com^$third-party ||getthislistbuildingvideo.biz^$third-party ||gettipsz.info^$third-party ||ggncpm.com^$third-party ||giantaffiliates.com^$third-party ||gigamega.su^$third-party ||gimiclub.com^$third-party ||gklmedia.com^$third-party ||glical.com^$third-party ||global-success-club.net^$third-party ||globaladsales.com^$third-party ||globaladv.net^$third-party ||globalinteractive.com^$third-party ||globalsuccessclub.com^$third-party ||globaltakeoff.net^$third-party ||glowdot.com^$third-party ||gmads.net^$third-party ||go2jump.org^$third-party ||go2media.org^$third-party ||go2speed.org^$third-party ||goember.com^$third-party ||gogoplexer.com^$third-party ||gojoingscnow.com^$third-party ||goodadvert.ru^$third-party ||goodadvertising.info^$third-party ||googleadservicepixel.com^$third-party ||googlesyndicatiion.com^$third-party ||googletagservices.com/tag/js/gpt_$third-party ||googletagservices.com/tag/static/$third-party ||gopjn.com^$third-party ||gorgonkil.com^$third-party ||gourmetads.com^$third-party ||governmenttrainingexchange.com^$third-party ||goviral-content.com^$third-party ||goviral.hs.llnwd.net^$third-party ||gpacalculatorhighschoolfree.com^$third-party ||grabmyads.com^$third-party ||grabo.bg^$third-party ||grafpedia.com^$third-party ||grapeshot.co.uk^$third-party ||gratisnetwork.com^$third-party ||greenads.org^$third-party ||greenlabelppc.com^$third-party ||grenstia.com^$third-party ||gretzalz.com^$third-party ||gripdownload.co^$third-party ||grllopa.com^$third-party ||groovinads.com^$third-party ||groupcommerce.com^$third-party ||gscontxt.net^$third-party ||gscsystemwithdarren.com^$third-party ||guardiandigitalcomparison.co.uk^$third-party ||guitaralliance.com^$third-party ||gumgum.com^$third-party ||gunpartners.com^$third-party ||gururevenue.com^$third-party ||gwallet.com^$third-party ||gx101.com^$third-party ||h-images.net^$third-party ||h12-media.com^$third-party ||halfpriceozarks.com^$third-party ||halogennetwork.com^$third-party ||hanaprop.com^$third-party ||harrenmedianetwork.com^$third-party ||havamedia.net^$third-party ||havetohave.com^$third-party ||hb-247.com^$third-party ||hd-plugin.com^$third-party ||hdplayer-download.com^$third-party ||hdvid-codecs-dl.net^$third-party ||hdvidcodecs.com^$third-party ||headup.com^$third-party ||healthaffiliatesnetwork.com^$third-party ||healthcarestars.com^$third-party ||hebiichigo.com^$third-party ||helloreverb.com^$third-party ||hexagram.com^$third-party ||hiadone.com^$third-party ||hijacksystem.com^$third-party ||hilltopads.net^$third-party ||himediads.com^$third-party ||himediadx.com^$third-party ||hiplair.com^$third-party ||hit-now.com^$third-party ||hits.sys.lv^$third-party ||hokaybo.com^$third-party ||holidaytravelguide.org^$third-party ||hopfeed.com^$third-party ||horse-racing-affiliate-program.co.uk^$third-party ||horsered.com^$third-party ||horyzon-media.com^$third-party ||hosticanaffiliate.com^$third-party ||hot-hits.us^$third-party ||hotelscombined.com.au^$third-party ||hotelscombined.com^$third-party ||hotfeed.net^$third-party ||hotkeys.com^$third-party ||hotptp.com^$third-party ||hotwords.com.br^$third-party ||hotwords.com.mx^$third-party ||hotwords.com^$third-party ||hover.in^$third-party ||hplose.de^$third-party ||hstpnetwork.com^$third-party ||httpool.com^$third-party ||httpsecurity.org^$third-party ||hype-ads.com^$third-party ||hypeads.org^$third-party ||hypemakers.net^$third-party ||hyperlinksecure.com^$third-party ||hypertrackeraff.com^$third-party ||hypervre.com^$third-party ||hyperwebads.com^$third-party ||i-media.co.nz^$third-party ||i.skimresources.com^$third-party ||iamediaserve.com^$third-party ||iasbetaffiliates.com^$third-party ||iasrv.com^$third-party ||ibannerexchange.com^$third-party ||ibatom.com^$third-party ||ibryte.com^$third-party ||icdirect.com^$third-party ||icqadvnew.com^$third-party ||idealmedia.com^$third-party ||identads.com^$third-party ||idownloadgalore.com^$third-party ||iframe.mediaplazza.com^$third-party ||igameunion.com^$third-party ||igloohq.com^$third-party ||ignitioninstaller.com^$third-party ||imasdk.googleapis.com^$third-party ||imedia.co.il^$third-party ||imediaaudiences.com^$third-party ||imediarevenue.com^$third-party ||img-giganto.net^$third-party ||imgfeedget.com^$third-party ||imglt.com^$third-party ||imgwebfeed.com^$third-party ||imho.ru^$third-party ||imiclk.com^$third-party ||impact-ad.jp^$third-party ||impactradius.com^$third-party ||implix.com^$third-party ||impresionesweb.com^$third-party ||impressionaffiliate.com^$third-party ||impressionaffiliate.mobi^$third-party ||impressioncontent.info^$third-party ||impressiondesk.com^$third-party ||impressionperformance.biz^$third-party ||impressionvalue.mobi^$third-party ||in-appadvertising.com^$third-party ||incentaclick.com^$third-party ||incomeliberation.com^$third-party ||increase-marketing.com^$third-party ||indexww.com^$third-party ||indiabanner.com^$third-party ||indiads.com^$third-party ||indianbannerexchange.com^$third-party ||indianlinkexchange.com^$third-party ||indicate.to^$third-party ||indieclick.com^$third-party ||indofad.com^$third-party ||industrybrains.com^$third-party ||inentasky.com^$third-party ||inetinteractive.com^$third-party ||infectiousmedia.com^$third-party ||infinite-ads.com^$third-party ||infinityads.com^$third-party ||influads.com^$third-party ||info4.a7.org^$third-party ||infolinks.com^$third-party ||information-sale.com^$third-party ||infra-ad.com^$third-party ||inktad.com^$third-party ||innity.com^$third-party ||innity.net^$third-party ||innovid.com^$third-party ||insightexpress.com^$third-party ||insightexpressai.com^$third-party ||insitepromotion.com^$third-party ||insitesystems.com^$third-party ||inskinad.com^$third-party ||inskinmedia.com^$~stylesheet,third-party ||insta-cash.net^$third-party ||instantbannercreator.com^$third-party ||instantdollarz.com^$third-party ||instinctiveads.com^$third-party ||instivate.com^$third-party ||integral-marketing.com^$third-party ||intellibanners.com^$third-party ||intellitxt.com^$third-party ||intenthq.com^$third-party ||intentmedia.net^$third-party ||interactivespot.net^$third-party ||interclick.com^$third-party ||interestably.com^$third-party ||interesting.cc^$third-party ||intermarkets.net^$third-party ||internetadbrokers.com^$third-party ||interpolls.com^$third-party ||interworksmedia.co.kr^$third-party ||intextdirect.com^$third-party ||intextscript.com^$third-party ||intextual.net^$third-party ||intgr.net^$third-party ||intopicmedia.com^$third-party ||inttrax.com^$third-party ||intuneads.com^$third-party ||inuvo.com^$third-party ||inuxu.co.in^$third-party ||investingchannel.com^$third-party ||inviziads.com^$third-party ||ip-adress.com^$third-party ||ipredictive.com^$third-party ||ipromote.com^$third-party ||isohits.com^$third-party ||isparkmedia.com^$third-party ||itrengia.com^$third-party ||iu16wmye.com^$third-party ||iv.doubleclick.net^$third-party ||iwantmoar.net^$third-party ||ixnp.com^$third-party ||izeads.com^$third-party ||j2ef76da3.website^$third-party ||jadcenter.com^$third-party ||jango.com^$third-party ||jangonetwork.com^$third-party ||jbrlsr.com^$third-party ||jdoqocy.com^$third-party ||jdproject.net^$third-party ||jeetyetmedia.com^$third-party ||jemmgroup.com^$third-party ||jiwire.com^$third-party ||jizzontoy.com^$third-party ||jmp9.com^$third-party ||jo7cofh3.com^$third-party ||jobsyndicate.com^$third-party ||jobtarget.com^$third-party ||joytocash.com^$third-party ||jque.net^$third-party ||js.cdn.ac^$third-party ||jscount.com^$third-party ||jsfeedadsget.com^$third-party ||jsretra.com^$third-party ||jssearch.net^$third-party ||jtrakk.com^$third-party ||judicated.com^$third-party ||juiceadv.com^$third-party ||juiceadv.net^$third-party ||jujuads.com^$third-party ||jujzh9va.com^$third-party ||jumboaffiliates.com^$third-party ||jumbolt.ru^$third-party ||jumpelead.com^$third-party ||jumptap.com^$third-party ||jursp.com^$third-party ||justrelevant.com^$third-party ||jwaavsze.com^$third-party ||jyvtidkx.com^$third-party ||k0z09okc.com^$third-party ||kanoodle.com^$third-party ||kantarmedia.com^$third-party ||kavanga.ru^$third-party ||keewurd.com^$third-party ||kehalim.com^$third-party ||kerg.net^$third-party ||ketoo.com^$third-party ||keywordblocks.com^$third-party ||kikuzip.com^$third-party ||kinley.com^$third-party ||kintokup.com^$third-party ||kiosked.com^$third-party ||kitnmedia.com^$third-party ||klikadvertising.com^$third-party ||kliksaya.com^$third-party ||klikvip.com^$third-party ||klipmart.com^$third-party ||klixfeed.com^$third-party ||kloapers.com^$third-party ||klonedaset.org^$third-party ||knorex.asia^$third-party ||knowd.com^$third-party ||kolition.com^$third-party ||komoona.com^$third-party ||kontextua.com^$third-party ||koocash.com^$third-party ||korrelate.net^$third-party ||kqzyfj.com^$third-party ||kr3vinsx.com^$third-party ||kromeleta.ru^$third-party ||kumpulblogger.com^$third-party ||l3op.info^$third-party ||ladbrokesaffiliates.com.au^$third-party ||lakequincy.com^$third-party ||lakidar.net^$third-party ||lanistaconcepts.com^$third-party ||largestable.com^$third-party ||laserhairremovalstore.com^$third-party ||launchbit.com^$third-party ||layer-ad.org^$third-party ||layerloop.com^$third-party ||layerwelt.com^$third-party ||lazynerd.info^$third-party ||lbm1.com^$third-party ||lcl2adserver.com^$third-party ||ldgateway.com^$third-party ||lduhtrp.net^$third-party ||leadacceptor.com^$third-party ||leadad.mobi^$third-party ||leadadvert.info^$third-party ||leadbolt.net^$third-party ||leadcola.com^$third-party ||leaderpub.fr^$third-party ||leadmediapartners.com^$third-party ||leetmedia.com^$third-party ||legisland.net^$third-party ||letsgoshopping.tk^$third-party ||lfstmedia.com^$third-party ||lgse.com^$third-party ||liftdna.com^$third-party ||ligational.com^$third-party ||ligatus.com^$third-party ||lightad.co.kr^$third-party ||lightningcast.net^$~object-subrequest,third-party ||linicom.co.il^$third-party ||linkbuddies.com^$third-party ||linkclicks.com^$third-party ||linkconnector.com^$third-party ||linkelevator.com^$third-party ||linkexchange.com^$third-party ||linkexchangers.net^$third-party ||linkgrand.com^$third-party ||linkmads.com^$third-party ||linkoffers.net^$third-party ||linkreferral.com^$third-party ||links.io^$third-party ||linkshowoff.com^$third-party ||linksmart.com^$third-party ||linkstorm.net^$third-party ||linksynergy.com^$third-party ||linkwash.de^$third-party ||linkworth.com^$third-party ||linkybank.com^$third-party ||linkz.net^$third-party ||liqwid.net^$third-party ||listingcafe.com^$third-party ||liveadoptimizer.com^$third-party ||liveadserver.net^$third-party ||liverail.com^$~object-subrequest,third-party ||liveuniversenetwork.com^$third-party ||loading-resource.com^$third-party ||localadbuy.com^$third-party ||localedgemedia.com^$third-party ||localsearch24.co.uk^$third-party ||lockhosts.com^$third-party ||logo-net.co.uk^$third-party ||loodyas.com^$third-party ||lookit-quick.com^$third-party ||looksmart.com^$third-party ||looneyads.com^$third-party ||looneynetwork.com^$third-party ||lose-ads.de^$third-party ||loseads.eu^$third-party ||losomy.com^$third-party ||lotteryaffiliates.com^$third-party ||love-banner.com^$third-party ||loxtk.com^$third-party ||lqcdn.com^$third-party ||lqw.me^$third-party ||ltassrv.com.s3.amazonaws.com^$third-party ||ltassrv.com/goads.swf ||ltassrv.com/serve/ ||lucidmedia.com^$third-party ||luminate.com^$third-party ||lushcrush.com^$third-party ||luxadv.com^$third-party ||luxbetaffiliates.com.au^$third-party ||luxup.ru^$third-party ||lx2rv.com^$third-party ||lzjl.com^$third-party ||m1.fwmrm.net^$object-subrequest,third-party ||m2pub.com^$third-party ||m4pub.com^$third-party ||m57ku6sm.com^$third-party ||m5prod.net^$third-party ||madadsmedia.com^$third-party ||madserving.com^$third-party ||madsone.com^$third-party ||magicalled.info^$third-party ||magnetisemedia.com^$third-party ||mainadv.com^$third-party ||mainroll.com^$third-party ||makecashtakingsurveys.biz^$third-party ||makemoneymakemoney.net^$third-party ||mallsponsor.com^$third-party ||mangoforex.com^$third-party ||marbil24.co.za^$third-party ||marfeel.com^$third-party ||marketbanker.com^$third-party ||marketfly.net^$third-party ||markethealth.com^$third-party ||marketingenhanced.com^$third-party ||marketleverage.com^$third-party ||marketnetwork.com^$third-party ||marketoring.com^$third-party ||marsads.com^$third-party ||martiniadnetwork.com^$third-party ||masternal.com^$third-party ||mastertraffic.cn^$third-party ||matiro.com^$third-party ||maudau.com^$third-party ||maxserving.com^$third-party ||mb01.com^$third-party ||mb102.com^$third-party ||mb104.com^$third-party ||mb38.com^$third-party ||mb57.com^$third-party ||mbn.com.ua^$third-party ||mdadvertising.net^$third-party ||mdialog.com^$third-party ||mdn2015x1.com^$third-party ||meadigital.com^$third-party ||media-general.com^$third-party ||media-ks.net^$third-party ||media-networks.ru^$third-party ||media-servers.net^$third-party ||media.net^$third-party ||media303.com^$third-party ||media6degrees.com^$third-party ||media970.com^$third-party ||mediaadserver.org^$third-party ||mediaclick.com^$third-party ||mediacpm.com^$third-party ||mediaffiliation.com^$third-party ||mediaflire.com^$third-party ||mediaforge.com^$third-party ||mediag4.com^$third-party ||mediagridwork.com^$third-party ||mediakeywords.com^$third-party ||medialand.ru^$third-party ||medialation.net^$third-party ||mediaonenetwork.net^$third-party ||mediaonpro.com^$third-party ||mediapeo.com^$third-party ||mediaplex.com^$third-party,domain=~watchever.de ||mediatarget.com^$third-party ||mediative.ca^$third-party ||mediatraffic.com^$third-party ||mediatraks.com^$third-party ||medleyads.com^$third-party ||medrx.sensis.com.au^$third-party ||medyanet.net^$third-party ||medyanetads.com^$third-party ||meendocash.com^$third-party ||meetic-partners.com^$third-party ||megacpm.com^$third-party ||megbase.com^$third-party ||meinlist.com^$third-party ||mentad.com^$third-party ||mentalks.ru^$third-party ||merchenta.com^$third-party ||mercuras.com^$third-party ||messagespaceads.com^$third-party ||metaffiliation.com^$~image,~subdocument,third-party ||metaffiliation.com^*^maff= ||metaffiliation.com^*^taff= ||metavertising.com^$third-party ||metavertizer.com^$third-party ||metrics.io^$third-party ||meviodisplayads.com^$third-party ||meya41w7.com^$third-party ||mezimedia.com^$third-party ||mgcash.com^$third-party ||mgcashgate.com^$third-party ||mgid.com^$third-party,domain=~marketgid.com|~marketgid.com.ua ||mgplatform.com^$third-party ||mibebu.com^$third-party ||microad.jp^$third-party ||microadinc.com^$third-party ||microsoftaffiliates.net^$third-party ||milabra.com^$third-party ||minimumpay.info^$third-party ||mirago.com^$third-party ||mirrorpersonalinjury.co.uk^$third-party ||miva.com^$third-party ||mixmarket.biz^$third-party ||mixpo.com^$third-party ||mktseek.com^$third-party ||mlnadvertising.com^$third-party ||mm1x.nl^$third-party ||mmadsgadget.com^$third-party ||mmgads.com^$third-party ||mmismm.com^$third-party ||mmngte.net^$third-party ||mmondi.com^$third-party ||mmotraffic.com^$third-party ||moatads.com^$third-party ||mobatori.com^$third-party ||mobatory.com^$third-party ||mobday.com^$third-party ||mobicont.com^$third-party ||mobifobi.com^$third-party ||mobikano.com^$third-party ||mobiright.com^$third-party ||mobisla.com^$third-party ||mobitracker.info^$third-party ||mobiyield.com^$third-party ||moborobot.com^$third-party ||mobstrks.com^$third-party ||mobtrks.com^$third-party ||mobytrks.com^$third-party ||modelegating.com^$third-party ||moffsets.com^$third-party ||mogointeractive.com^$third-party ||mojoaffiliates.com^$third-party ||mokonocdn.com^$third-party ||money-cpm.fr^$third-party ||money4ads.com^$third-party ||moneycosmos.com^$third-party ||moneywhisper.com^$third-party ||monkeybroker.net^$third-party ||monsoonads.com^$third-party ||mookie1.com^$third-party ||mootermedia.com^$third-party ||mooxar.com^$third-party ||moregamers.com^$third-party ||moreplayerz.com^$third-party ||morgdm.ru^$third-party ||moselats.com^$third-party ||movad.net^$third-party ||mpnrs.com^$third-party ||mpression.net^$third-party ||mprezchc.com^$third-party ||msads.net^$third-party ||mtrcss.com^$third-party ||mujap.com^$third-party ||multiadserv.com^$third-party ||munically.com^$third-party ||music-desktop.com^$third-party ||mutary.com^$third-party ||mxtads.com^$third-party ||my-layer.net^$third-party ||myaffiliates.com^$third-party ||myclickbankads.com^$third-party ||mycooliframe.net^$third-party ||mydreamads.com^$third-party ||myemailbox.info^$third-party ||myinfotopia.com^$third-party ||mylinkbox.com^$third-party ||mynewcarquote.us^$third-party ||myplayerhd.net^$third-party ||mythings.com^$third-party ||myuniques.ru^$third-party ||myvads.com^$third-party ||mz28ismn.com^$third-party ||n388hkxg.com^$third-party ||n4403ad.doubleclick.net^$third-party ||nabbr.com^$third-party ||nagrande.com^$third-party ||nanigans.com^$third-party ||nativead.co^$third-party ||nativeads.com^$third-party ||nbjmp.com^$third-party ||nbstatic.com^$third-party ||ncrjsserver.com^$third-party ||neblotech.com^$third-party ||negolist.com^$third-party ||neobux.com^$third-party ||neodatagroup.com^$third-party ||neoffic.com^$third-party ||net-ad-vantage.com^$third-party ||net3media.com^$third-party ||netaffiliation.com^$~script,third-party ||netavenir.com^$third-party ||netflixalternative.net^$third-party ||netliker.com^$third-party ||netloader.cc^$third-party ||netpondads.com^$third-party ||netseer.com^$third-party ||netshelter.net^$third-party ||netsolads.com^$third-party ||networkplay.in^$third-party ||networkxi.com^$third-party ||networld.hk^$third-party ||networldmedia.net^$third-party ||neudesicmediagroup.com^$third-party ||newdosug.eu^$third-party ||newgentraffic.com^$third-party ||newideasdaily.com^$third-party ||newsadstream.com^$third-party ||newsnet.in.ua^$third-party ||newstogram.com^$third-party ||newtention.net^$third-party ||nexac.com^$third-party ||nexage.com^$third-party ||nextmobilecash.com^$third-party ||ngecity.com^$third-party ||nicheadgenerator.com^$third-party ||nicheads.com^$third-party ||nighter.club^$third-party ||nkredir.com^$third-party ||nmcdn.us^$third-party ||nmwrdr.net^$third-party ||nobleppc.com^$third-party ||nobsetfinvestor.com^$third-party ||nonstoppartner.de^$third-party ||noretia.com^$third-party ||normkela.com^$third-party ||northmay.com^$third-party ||nowlooking.net^$third-party ||nowspots.com^$third-party ||nplexmedia.com^$third-party ||npvos.com^$third-party ||nquchhfyex.com^$third-party ||nrnma.com^$third-party ||nscontext.com^$third-party ||nsdsvc.com^$third-party ||nsmartad.com^$third-party ||nspmotion.com^$third-party ||nster.net^$third-party,domain=~nster.com ||ntent.com^$third-party ||numberium.com^$third-party ||nuseek.com^$third-party ||nvadn.com^$third-party ||nvero.net^$third-party ||nwfhalifax.com^$third-party ||nxtck.com^$third-party ||nyadmcncserve-05y06a.com^$third-party ||nzads.net.nz^$third-party ||nzphoenix.com^$third-party ||oads.co^$third-party ||oainternetservices.com^$third-party ||obesw.com^$third-party ||obeus.com^$third-party ||obibanners.com^$third-party ||objects.tremormedia.com^$~object-subrequest,third-party ||objectservers.com^$third-party ||oceanwebcraft.com^$third-party ||oclasrv.com^$third-party ||oclsasrv.com^$third-party ||oclus.com^$third-party ||oehposan.com^$third-party ||offeradvertising.biz^$third-party ||offerforge.com^$third-party ||offerpalads.com^$third-party ||offerserve.com^$third-party ||offersquared.com^$third-party ||ofino.ru^$third-party ||oggifinogi.com^$third-party ||ohmcasting.com^$third-party ||oldtiger.net^$third-party ||omclick.com^$third-party ||omg2.com^$third-party ||omgpm.com^$third-party ||omguk.com^$third-party ||onad.eu^$third-party ||onads.com^$third-party ||onclickads.net^$third-party ||onedmp.com^$third-party ||onenetworkdirect.com^$third-party ||onenetworkdirect.net^$third-party ||onespot.com^$third-party ||online-adnetwork.com^$third-party ||online-media24.de^$third-party ||onlineadtracker.co.uk^$third-party ||onlinedl.info^$third-party ||onlyalad.net^$third-party ||onrampadvertising.com^$third-party ||onscroll.com^$third-party ||onsitemarketplace.net^$third-party ||onvertise.com^$third-party ||oodode.com^$third-party ||ooecyaauiz.com^$third-party ||oofte.com^$third-party ||oos4l.com^$third-party ||opap.co.kr^$third-party ||openbook.net^$third-party ||openetray.com^$third-party ||opensourceadvertisementnetwork.info^$third-party ||openxadexchange.com^$third-party ||openxenterprise.com^$third-party ||openxmarket.asia^$third-party ||operatical.com^$third-party ||opt-intelligence.com^$third-party ||opt-n.net^$third-party ||opteama.com^$third-party ||optiad.net^$third-party ||optimalroi.info^$third-party ||optimatic.com^$third-party ||optimizeadvert.biz^$third-party ||optinemailpro.com^$third-party ||orangeads.fr^$third-party ||orarala.com^$third-party ||orbengine.com^$third-party ||oskale.ru^$third-party ||ospreymedialp.com^$third-party ||othersonline.com^$third-party ||ourunlimitedleads.com^$third-party ||oveld.com^$third-party ||overture.com^$third-party ||overturs.com^$third-party ||oxado.com^$third-party ||oxsng.com^$third-party ||oxtracking.com^$third-party ||ozertesa.com^$third-party ||ozonemedia.com^$third-party ||p-advg.com^$third-party ||p-comme-performance.com^$third-party ||p-digital-server.com^$third-party ||p2ads.com^$third-party ||paads.dk^$third-party ||padsdelivery.com^$third-party ||padstm.com^$third-party ||pagefair.net^$third-party ||pagesinxt.com^$third-party ||paid4ad.de^$third-party ||paidonresults.net^$third-party ||paidsearchexperts.com^$third-party ||pakbanners.com^$third-party ||panachetech.com^$third-party ||pantherads.com^$third-party ||paperg.com^$third-party ||paradocs.ru^$third-party ||partner-ads.com^$third-party ||partner.googleadservices.com^$third-party ||partner.video.syndication.msn.com^$~object-subrequest,third-party ||partnerearning.com^$third-party ||partnermax.de^$third-party ||partycasino.com^$third-party ||partypartners.com^$third-party ||partypoker.com^$third-party ||passionfruitads.com^$third-party ||pautaspr.com^$third-party ||pay-click.ru^$third-party ||paydotcom.com^$third-party ||payperpost.com^$third-party ||pc-ads.com^$third-party ||pe2k2dty.com^$third-party ||peakclick.com^$third-party ||peelawaymaker.com^$third-party ||peemee.com^$third-party ||peer39.net^$third-party ||penuma.com^$third-party ||pepperjamnetwork.com^$third-party ||percularity.com^$third-party ||perfb.com^$third-party ||perfcreatives.com^$third-party ||perfoormapp.info^$third-party ||performance-based.com^$third-party ||performanceadvertising.mobi^$third-party ||performancetrack.info^$third-party ||performancingads.com^$third-party ||permutive.com^$third-party ||pezrphjl.com^$third-party ||pgmediaserve.com^$third-party ||pgpartner.com^$third-party ||pgssl.com^$third-party ||pharmcash.com^$third-party ||pheedo.com^$third-party ||philbardre.com^$third-party ||philipstreehouse.info^$third-party ||philosophere.com^$third-party ||phonespybubble.com^$third-party ||pianobuyerdeals.com^$third-party ||picadmedia.com^$third-party ||picbucks.com^$third-party ||picsti.com^$third-party ||pictela.net^$third-party ||pinballpublishernetwork.com^$third-party ||pioneeringad.com^$third-party ||pivotalmedialabs.com^$third-party ||pivotrunner.com^$third-party ||pixazza.com^$third-party ||pixeltrack66.com^$third-party ||pixfuture.net^$third-party ||pixxur.com^$third-party ||pjatr.com^$third-party ||pjtra.com^$third-party ||platinumadvertisement.com^$third-party ||play24.us^$third-party ||playertraffic.com^$third-party ||pleeko.com^$third-party ||plenomedia.com^$third-party ||pllddc.com^$third-party ||plocap.com^$third-party ||plugerr.com^$third-party ||plusfind.net^$third-party ||plxserve.com^$third-party ||pmsrvr.com^$third-party ||pnoss.com^$third-party ||pntra.com^$third-party ||pntrac.com^$third-party ||pntrs.com^$third-party ||pointclicktrack.com^$third-party ||pointroll.com^$third-party ||points2shop.com^$third-party ||polluxnetwork.com^$third-party ||polmontventures.com^$third-party ||polyad.net^$third-party ||polydarth.com^$third-party ||popads.net^$third-party ||popadscdn.net^$third-party ||popcash.net^$third-party ||popcpm.com^$third-party ||popcpv.com^$third-party ||popearn.com^$third-party ||popmarker.com^$third-party ||popmyad.com^$third-party ||popmyads.com^$third-party ||poponclick.com^$third-party ||popsads.com^$third-party ||popshow.info^$third-party ||poptarts.me^$third-party ||popularitish.com^$third-party ||popularmedia.net^$third-party ||populis.com^$third-party ||populisengage.com^$third-party ||popunder.ru^$third-party ||popunderz.com^$third-party ||popuptraffic.com^$third-party ||popupvia.com^$third-party ||pornv.org^$third-party ||posternel.com^$third-party ||postrelease.com^$third-party ||poweradvertising.co.uk^$third-party ||powerfulbusiness.net^$third-party ||powerlinks.com^$third-party ||ppcindo.com^$third-party ||ppclinking.com^$third-party ||ppctrck.com^$third-party ||ppcwebspy.com^$third-party ||ppsearcher.ru^$third-party ||precisionclick.com^$third-party ||predictad.com^$third-party ||prestadsng.com^$third-party ||prexista.com^$third-party ||prf.hn^$third-party ||prickac.com^$third-party ||primaryads.com^$third-party ||pro-advert.de^$third-party ||pro-advertising.com^$third-party ||pro-market.net^$third-party ||proadsdirect.com^$third-party ||probannerswap.com^$third-party ||prod.untd.com^$third-party ||proffigurufast.com^$third-party ||profitpeelers.com^$third-party ||programresolver.net^$third-party ||projectwonderful.com^$third-party ||promo-reklama.ru^$third-party ||promobenef.com^$third-party ||promotionoffer.mobi^$third-party ||promotiontrack.mobi^$third-party ||propellerads.com^$third-party ||propellerpops.com^$third-party ||propelplus.com^$third-party ||prosperent.com^$third-party ||protally.net^$third-party ||proximic.com^$third-party ||prre.ru^$third-party ||psclicks.com^$third-party ||pseqcs05.com^$third-party ||ptmzr.com^$third-party ||ptp.lolco.net^$third-party ||ptp22.com^$third-party ||ptp24.com^$third-party ||pub-fit.com^$third-party ||pubdirecte.com^$third-party,domain=~debrideurstream.fr ||pubgears.com^$third-party ||publicidad.net^$third-party ||publicidees.com^$third-party ||publicityclerks.com^$third-party ||publisher.to^$third-party ||publisheradnetwork.com^$third-party ||pubmatic.com^$third-party ||pubserve.net^$third-party ||pubted.com^$third-party ||pulse360.com^$third-party ||pulsemgr.com^$third-party ||purpleflag.net^$third-party ||push2check.com^$third-party ||pxlad.io^$third-party ||pzaasocba.com^$third-party ||pzuwqncdai.com^$third-party ||q1media.com^$third-party ||q1mediahydraplatform.com^$third-party ||q1xyxm89.com^$third-party ||qadservice.com^$third-party ||qdmil.com^$third-party ||qksrv.net^$third-party ||qksz.net^$third-party ||qnrzmapdcc.com^$third-party ||qnsr.com^$third-party ||qservz.com^$third-party ||quantumads.com^$third-party ||quensillo.com^$third-party ||questionmarket.com^$third-party ||questus.com^$third-party ||quickcash500.com^$third-party ||quinstreet.com^$third-party ||qwobl.net^$third-party ||qwzmje9w.com^$third-party ||rabilitan.com^$third-party ||radeant.com^$third-party ||radicalwealthformula.com^$third-party ||radiusmarketing.com^$third-party ||raiggy.com^$third-party ||rainbowtgx.com^$third-party ||rainwealth.com^$third-party ||rampanel.com^$third-party ||rapt.com^$third-party ||rawasy.com^$third-party ||rbnt.org^$third-party ||rcads.net^$third-party ||rcurn.com^$third-party ||rddywd.com^$third-party ||reachjunction.com^$third-party ||reachlocal.com^$third-party ||reachmode.com^$third-party ||readserver.net^$third-party ||realclick.co.kr^$third-party ||realmatch.com^$third-party ||realmedia.com^$third-party ||realsecuredredirect.com^$third-party ||realvu.net^$third-party ||recomendedsite.com^$third-party ||redcourtside.com^$third-party ||redintelligence.net^$third-party ||reduxmediagroup.com^$third-party ||reelcentric.com^$third-party ||refban.com^$third-party ||referback.com^$third-party ||regdfh.info^$third-party ||registry.cw.cm^$third-party ||regurgical.com^$third-party ||reklamz.com^$third-party ||relatedweboffers.com^$third-party ||relestar.com^$third-party ||relevanti.com^$third-party ||relytec.com^$third-party ||remiroyal.ro^$third-party ||resideral.com^$third-party ||respecific.net^$third-party ||respond-adserver.cloudapp.net^$third-party ||respondhq.com^$third-party ||resultlinks.com^$third-party ||resultsz.com^$third-party ||retargeter.com^$third-party ||reussissonsensemble.fr^$third-party ||rev2pub.com^$third-party ||revcontent.com^$third-party ||revenue.com^$third-party ||revenuegiants.com^$third-party ||revenuehits.com^$third-party ||revenuemantra.com^$third-party ||revenuemax.de^$third-party ||revfusion.net^$third-party ||revmob.com^$third-party ||revokinets.com^$third-party ||revresda.com^$third-party ||revresponse.com^$third-party ||revsci.net^$third-party ||rewardisement.com^$third-party ||rewardsaffiliates.com^$third-party ||rewardstyle.com^$third-party ||rfihub.net^$third-party ||rhown.com^$third-party ||ricead.com^$third-party ||richmedia247.com^$third-party ||richwebmedia.com^$third-party ||ringrevenue.com^$third-party ||ringtonematcher.com^$third-party ||ringtonepartner.com^$third-party ||ripplead.com^$third-party ||riverbanksand.com^$third-party ||rixaka.com^$third-party ||rmxads.com^$third-party ||rnmd.net^$third-party ||robocat.me^$third-party ||rocketier.net^$third-party ||rogueaffiliatesystem.com^$third-party ||roicharger.com^$third-party ||roirocket.com^$third-party ||romance-net.com^$third-party ||rotaban.ru^$third-party ||rotatingad.com^$third-party ||rotorads.com^$third-party ||rovion.com^$third-party ||roxyaffiliates.com^$third-party ||rtbidder.net^$third-party ||rtbmedia.org^$third-party ||rtbpop.com^$third-party ||rtbpops.com^$third-party ||rubiconproject.com^$third-party ||rummyaffiliates.com^$third-party ||runadtag.com^$third-party ||rwpads.com^$third-party ||ryminos.com^$third-party ||s2d6.com^$third-party ||sa.entireweb.com^$third-party ||safeadnetworkdata.net^$third-party ||safecllc.com^$third-party ||safelistextreme.com^$third-party ||saltamendors.com^$third-party ||salvador24.com^$third-party ||saple.net^$third-party ||satgreera.com^$third-party ||saveads.net^$third-party ||saveads.org^$third-party ||sayadcoltd.com^$third-party ||saymedia.com^$third-party ||sba.about.co.kr^$third-party ||sbaffiliates.com^$third-party ||sbcpower.com^$third-party ||scanmedios.com^$third-party ||scanscout.com^$third-party ||sceno.ru^$third-party ||scootloor.com^$third-party ||scratchaffs.com^$third-party ||search123.uk.com^$third-party ||seccoads.com^$third-party ||secondstreetmedia.com^$third-party ||secure-softwaremanager.com^$third-party ||securesoft.info^$third-party ||securewebsiteaccess.com^$third-party ||securitain.com^$third-party ||sedoparking.com^$third-party ||seductionprofits.com^$third-party ||seekads.net^$third-party ||sekindo.com^$third-party ||sellhealth.com^$third-party ||selsin.net^$third-party ||sendptp.com^$third-party ||senzapudore.net^$third-party ||serialbay.com^$third-party ||seriousfiles.com^$third-party ||servali.net^$third-party ||serve-sys.com^$third-party ||servebom.com^$third-party ||servedbyadbutler.com^$third-party ||servedbyopenx.com^$third-party ||servemeads.com^$third-party ||serving-sys.com^$third-party ||sethads.info^$third-party ||sev4ifmxa.com^$third-party ||sevenads.net^$third-party ||sevendaystart.com^$third-party ||sexmoney.com^$third-party ||shakamech.com^$third-party ||share-server.com^$third-party ||shareasale.com^$third-party ||sharegods.com^$third-party ||shareresults.com^$third-party ||sharethrough.com^$third-party ||shoogloonetwork.com^$third-party ||shopalyst.com^$third-party ||shoppingads.com^$third-party ||showyoursite.com^$third-party ||siamzone.com^$third-party ||silence-ads.com^$third-party ||silstavo.com^$third-party ||silverads.net^$third-party ||simpio.com^$third-party ||simply.com^$third-party ||simplyhired.com^$third-party ||sitebrand.com^$third-party ||siteencore.com^$third-party ||sitescout.com^$third-party ||sitescoutadserver.com^$third-party ||sitesense-oo.com^$third-party ||sitethree.com^$third-party ||sittiad.com^$third-party ||skimlinks.com^$third-party ||skinected.com^$third-party ||skoovyads.com^$third-party ||skyactivate.com^$third-party ||skyscrpr.com^$third-party ||slimspots.com^$third-party ||slimtrade.com^$third-party ||slinse.com^$third-party ||smart-feed-online.com^$third-party ||smart.allocine.fr^$third-party ||smart2.allocine.fr^$third-party ||smartad.ee^$third-party ||smartadserver.com^$third-party ||smartdevicemedia.com^$third-party ||smarterdownloads.net^$third-party ||smarttargetting.co.uk^$third-party ||smarttargetting.com^$third-party ||smarttargetting.net^$third-party ||smarttds.ru^$third-party ||smileycentral.com^$third-party ||smilyes4u.com^$third-party ||smowtion.com^$third-party ||smpgfx.com^$third-party ||sms-mmm.com^$third-party ||sn00.net^$third-party ||snap.com^$third-party ||sndkorea.co.kr^$third-party ||so-excited.com^$third-party ||sochr.com^$third-party ||socialbirth.com^$third-party ||socialelective.com^$third-party ||sociallypublish.com^$third-party ||socialmedia.com^$third-party ||socialreach.com^$third-party ||socialspark.com^$third-party ||society6.com^$third-party ||sociocast.com^$third-party ||sociomantic.com^$third-party ||sodud.com^$third-party ||soft4dle.com^$third-party ||softonicads.com^$third-party ||softpopads.com^$third-party ||sokitosa.com^$third-party ||solapoka.com^$third-party ||solarmosa.com^$third-party ||solocpm.com^$third-party ||solutionzip.info^$third-party ||sonnerie.net^$third-party ||sonobi.com^$third-party ||sophiasearch.com^$third-party ||sparkstudios.com^$third-party ||specificclick.net^$third-party ||specificmedia.com^$third-party ||spectato.com^$third-party ||speeb.com^$third-party ||speedshiftmedia.com^$third-party ||speedsuccess.net^$third-party ||spiderhood.net^$third-party ||spinbox.freedom.com^$third-party ||spinbox.net^$third-party ||splinky.com^$third-party ||splut.com^$third-party ||spmxs.com^$third-party ||spongecell.com^$third-party ||sponsoredby.me^$third-party ||sponsoredtweets.com^$third-party ||sponsormob.com^$third-party ||sponsorpalace.com^$third-party ||sponsorpay.com^$third-party ||sponsorselect.com^$third-party ||sportsyndicator.com^$third-party ||spotrails.com^$third-party ||spotscenered.info^$third-party ||spottt.com^$third-party ||spotxchange.com^$third-party ||sprintrade.com^$third-party ||sproose.com^$third-party ||sq2trk2.com^$third-party ||srtk.net^$third-party ||srx.com.sg^$third-party ||sta-ads.com^$third-party ||stackadapt.com^$third-party ||stackattacka.com^$third-party ||stalesplit.com^$third-party ||standartads.com^$third-party ||star-advertising.com^$third-party ||stargamesaffiliate.com^$third-party ||starlayer.com^$third-party ||startpagea.com^$third-party ||statcamp.net^$third-party ||statelead.com^$third-party ||stealthlockers.com^$third-party ||stickyadstv.com^$third-party ||stocker.bonnint.net^$third-party ||streamate.com^$third-party ||streamdownloadonline.com^$third-party ||strikead.com^$third-party ||struq.com^$third-party ||style-eyes.eu^$third-party ||sublimemedia.net^$third-party ||submitexpress.co.uk^$third-party ||suggesttool.com^$third-party ||suite6ixty6ix.com^$third-party ||suitesmart.com^$third-party ||sumarketing.co.uk^$third-party ||sunmedia.net^$third-party ||suparewards.com^$third-party ||super-links.net^$third-party ||superloofy.com^$third-party ||supersitetime.com^$third-party ||supplyframe.com^$third-party ||supremeadsonline.com^$third-party ||surf-bar-traffic.com^$third-party ||survey-poll.com^$third-party ||surveyvalue.mobi^$third-party ||surveyvalue.net^$third-party ||surveywidget.biz^$third-party ||suthome.com^$third-party ||svlu.net^$third-party ||swadvertising.org^$third-party ||swbdds.com^$third-party ||swelen.com^$third-party ||switchadhub.com^$third-party ||swoop.com^$third-party ||symbiosting.com^$third-party ||syndicatedsearchresults.com^$third-party ||t3q7af0z.com^$third-party ||tacastas.com^$third-party ||tacoda.net^$third-party ||tacticalrepublic.com^$third-party ||tafmaster.com^$third-party ||taggify.net^$third-party ||tagjunction.com^$third-party ||tagshost.com^$third-party ||tailsweep.com^$third-party ||takensparks.com^$third-party ||talaropa.com^$third-party ||tangozebra.com^$third-party ||tapad.com^$third-party ||tardangro.com^$third-party ||targetadverts.com^$third-party ||targetnet.com^$third-party ||targetpoint.com^$third-party ||targetspot.com^$third-party ||tattomedia.com^$third-party ||tbaffiliate.com^$third-party ||tcadops.ca^$third-party ||td553.com^$third-party ||teads.tv^$third-party ||teambetaffiliates.com^$third-party ||teasernet.com^$third-party ||techclicks.net^$third-party ||technoratimedia.com^$third-party ||telemetryverification.net^$third-party ||teosredic.com^$third-party ||teracent.net^$third-party ||teracreative.com^$third-party ||testfilter.com^$third-party ||testnet.nl^$third-party ||text-link-ads.com^$third-party ||textonlyads.com^$third-party ||textsrv.com^$third-party ||tfag.de^$third-party ||tgtmedia.com^$third-party ||theads.me^$third-party ||thebannerexchange.com^$third-party ||thebflix.info^$third-party ||theequalground.info^$third-party ||thelistassassin.com^$third-party ||theloungenet.com^$third-party ||themidnightmatulas.com^$third-party ||thepiratereactor.net^$third-party ||thewebgemnetwork.com^$third-party ||thewheelof.com^$third-party ||thoseads.com^$third-party ||thoughtleadr.com^$third-party ||thoughtsondance.info^$third-party ||tidaltv.com^$third-party ||tinbuadserv.com^$third-party ||tisadama.com^$third-party ||tiser.com^$third-party ||tissage-extension.com^$third-party ||tkqlhce.com^$third-party ||tldadserv.com^$third-party ||tlvmedia.com^$third-party ||tnyzin.ru^$third-party ||toboads.com^$third-party ||tokenads.com^$third-party ||tollfreeforwarding.com^$third-party ||tomekas.com^$third-party ||tonefuse.com^$third-party ||tool-site.com^$third-party ||top26.net^$third-party ||topauto10.com^$third-party ||topcasino10.com^$third-party ||topeuro.biz^$third-party ||topfox.co.uk^$third-party ||tophotoffers.com^$third-party ||torads.me^$third-party ||torconpro.com^$third-party ||toroadvertising.com^$third-party ||torrida.net^$third-party ||torrpedoads.net^$third-party ||total-media.net^$third-party ||totalprofitplan.com^$third-party ||totemcash.com^$third-party ||tower-colocation.de^$third-party ||tower-colocation.info^$third-party ||tpnads.com^$third-party ||tqlkg.com^$third-party ||tqlkg.net^$third-party ||traceadmanager.com^$third-party ||trackadvertising.net^$third-party ||trackcorner.com^$third-party ||tracking.to^$third-party ||tracking101.com^$third-party ||tracking11.com^$third-party ||trackingoffer.info^$third-party ||trackingoffer.net^$third-party ||trackpath.biz^$third-party ||trackpromotion.net^$third-party ||trackstarsengland.net^$third-party ||trackthatad.com^$third-party ||tracktor.co.uk^$third-party ||trackword.net^$third-party ||trackyourlinks.com^$third-party ||tradedoubler.com^$third-party ||tradeexpert.net^$third-party ||tradepopups.com^$third-party ||traff-advertazer.com^$third-party ||traffboost.net^$third-party ||traffic-supremacy.com^$third-party ||trafficbarads.com^$third-party ||trafficbroker.com^$third-party ||trafficfactory.biz^$third-party ||trafficforce.com^$third-party ||traffichaus.com^$third-party ||trafficjunky.net^$third-party ||trafficmasterz.net^$third-party ||trafficmp.com^$third-party ||trafficrevenue.net^$third-party ||trafficspaces.net^$third-party ||trafficswarm.com^$third-party ||trafficsway.com^$third-party ||trafficsynergy.com^$third-party ||traffictrader.net^$third-party ||trafficular.com^$third-party ||trafficvance.com^$third-party ||trafficwave.net^$third-party ||trafficz.com^$third-party ||trafficzap.com^$third-party ||traffirms.com^$third-party ||trahic.ru^$third-party ||trapasol.com^$third-party ||traveladvertising.com^$third-party ||travelscream.com^$third-party ||travidia.com^$third-party ||tredirect.com^$third-party ||trenpyle.com^$third-party ||triadmedianetwork.com^$third-party ||tribalfusion.com^$third-party ||trigami.com^$third-party ||trk4.com^$third-party ||trkalot.com^$third-party ||trkclk.net^$third-party ||trker.com^$third-party ||trklnks.com^$third-party ||trks.us^$third-party ||trtrccl.com^$third-party ||trygen.co.uk^$third-party ||ttzmedia.com^$third-party ||tubberlo.com^$third-party ||tubemogul.com^$third-party ||tubereplay.com^$third-party ||tumri.net^$third-party ||turbotraff.net^$third-party ||turn.com^$third-party ||tusno.com^$third-party ||tutvp.com^$third-party ||tvprocessing.com^$third-party ||twalm.com^$third-party ||tweard.com^$third-party ||twinpinenetwork.com^$third-party ||twistads.com^$third-party ||twittad.com^$third-party ||twtad.com^$third-party ||tyroo.com^$third-party ||u-ad.info^$third-party ||u1hw38x0.com^$third-party ||ubudigital.com^$third-party ||udmserve.net^$third-party ||ugaral.com^$third-party ||ughus.com^$third-party ||uglyst.com^$third-party ||uiadserver.com^$third-party ||uiqatnpooq.com^$third-party ||ukbanners.com^$third-party ||unanimis.co.uk^$third-party ||underclick.ru^$third-party ||undertone.com^$third-party ||unicast.com^$third-party ||unitethecows.com^$third-party ||universityofinternetscience.com^$third-party ||unlockr.com^$third-party ||unrulymedia.com^$third-party ||unterary.com^$third-party ||upads.info^$third-party ||upliftsearch.com^$third-party ||urbation.net^$third-party ||ureace.com^$third-party ||urlads.net^$third-party ||urlcash.net^$third-party ||usbanners.com^$third-party ||usemax.de^$third-party ||usenetjunction.com^$third-party ||usenetpassport.com^$third-party ||usercash.com^$third-party ||usurv.com^$third-party ||utarget.co.uk^$third-party ||utarget.ru^$third-party ||utokapa.com^$third-party ||utubeconverter.com^$third-party ||v.fwmrm.net^$object-subrequest,third-party ||v.movad.de^$third-party ||v11media.com^$third-party ||v2cigs.com^$third-party ||v2mlblack.biz^$third-party ||vadpay.com^$third-party ||validclick.com^$third-party ||valuead.com^$third-party ||valueaffiliate.net^$third-party ||valueclick.com^$third-party ||valueclick.net^$third-party ||valueclickmedia.com^$third-party ||valuecommerce.com^$third-party ||valuecontent.net^$third-party ||vapedia.com^$third-party ||vcmedia.com^$third-party ||vcommission.com^$third-party ||vdopia.com^$third-party ||vectorstock.com^$third-party ||vellde.com^$third-party ||velmedia.net^$third-party ||velti.com^$third-party ||vemba.com^$third-party ||vendexo.com^$third-party ||veoxa.com^$third-party ||versahq.com^$third-party ||versetime.com^$third-party ||vhmnetwork.com^$third-party ||vianadserver.com^$third-party ||vibrant.co^$third-party ||vibrantmedia.com^$third-party ||video-loader.com^$third-party ||video1404.info^$third-party ||videoadex.com^$third-party ||videoclick.ru^$third-party ||videodeals.com^$third-party ||videoegg.com^$third-party ||videohub.com^$third-party ||videolansoftware.com^$third-party ||videologygroup.com^$third-party ||videoplaza.com^$object-subrequest,third-party,domain=autoexpress.co.uk|evo.co.uk|givemefootball.com|mensfitness.co.uk|mpora.com|tribalfootball.com ||videoplaza.com^$~object-subrequest,third-party ||videoplaza.tv/proxy/distributor^$object-subrequest,third-party ||videoplaza.tv^$object-subrequest,third-party,domain=tv4play.se ||videoplaza.tv^$~object-subrequest,third-party ||vidpay.com^$third-party ||viedeo2k.tv^$third-party ||view-ads.de^$third-party ||view.atdmt.com^*/iview/$third-party ||viewablemedia.net^$third-party ||viewclc.com^$third-party ||viewex.co.uk^$third-party ||viewivo.com^$third-party ||vindicosuite.com^$third-party ||vipcpms.com^$third-party ||vipquesting.com^$third-party ||visiads.com^$third-party ||visiblegains.com^$third-party ||visiblemeasures.com^$~object-subrequest,third-party ||visitdetails.com^$third-party ||visitweb.com^$third-party ||visualsteel.net^$third-party ||vitalads.net^$third-party ||vivamob.net^$third-party ||vntsm.com^$third-party ||vogosita.com^$third-party ||vpico.com^$third-party ||vs20060817.com^$third-party ||vs4entertainment.com^$third-party ||vs4family.com^$third-party ||vsservers.net^$third-party ||vth05dse.com^$third-party ||vuiads.de^$third-party ||vuiads.info^$third-party ||vuiads.net^$third-party ||w00tads.com^$third-party ||w00tmedia.net^$third-party ||w3exit.com^$third-party ||w4.com^$third-party ||w5statistics.info^$third-party ||w9statistics.info^$third-party ||wagershare.com^$third-party ||wahoha.com^$third-party ||wamnetwork.com^$third-party ||wangfenxi.com^$third-party ||warezlayer.to^$third-party ||warfacco.com^$third-party ||watchfree.flv.in^$third-party ||wateristian.com^$third-party ||waymp.com^$third-party ||wbptqzmv.com^$third-party ||wcmcs.net^$third-party ||wcpanalytics.com^$third-party ||web-adservice.com^$third-party ||webads.co.nz^$third-party ||webads.nl^$third-party ||webadvertise123.com^$third-party ||webgains.com^$third-party ||webmedia.co.il^$third-party ||weborama.fr^$third-party ||webseeds.com^$third-party ||webtraffic.ttinet.com^$third-party ||webusersurvey.com^$third-party ||wegetpaid.net^$third-party ||wegotmedia.com^$third-party ||werbe-sponsor.de^$third-party ||wfnetwork.com^$third-party ||wgreatdream.com^$third-party ||wh5kb0u4.com^$third-party ||where.com^$third-party ||whtsrv9.com^$third-party ||why-outsource.net^$third-party ||widget.yavli.com^$third-party ||widgetadvertising.biz^$third-party ||widgetbanner.mobi^$third-party ||widgetbucks.com^$third-party ||widgetlead.net^$third-party ||widgets.fccinteractive.com^$third-party ||widgetsurvey.biz^$third-party ||widgetvalue.net^$third-party ||widgetwidget.mobi^$third-party ||wigetmedia.com^$third-party ||wigetstudios.com^$third-party ||winbuyer.com^$third-party ||wingads.com^$third-party ||winsspeeder.info^$third-party ||wlmarketing.com^$third-party ||wmmediacorp.com^$third-party ||wonclick.com^$third-party ||wootmedia.net^$third-party ||wordbankads.com^$third-party ||wordego.com^$third-party ||worlddatinghere.com^$third-party ||worthathousandwords.com^$third-party ||worthyadvertising.com^$third-party ||wulium.com^$third-party ||wurea.com^$third-party ||wwbn.com^$third-party ||wwv4ez0n.com^$third-party ||wwwadcntr.com^$third-party ||wwwpromoter.com^$third-party ||x.mochiads.com^$third-party ||x4300tiz.com^$third-party ||xad.com^$third-party ||xadcentral.com^$third-party ||xcelltech.com^$third-party ||xcelsiusadserver.com^$third-party ||xchangebanners.com^$third-party ||xdev.info^$third-party ||xeontopa.com^$third-party ||xfs5yhr1.com^$third-party ||xgraph.net^$third-party ||xjfjx8hw.com^$third-party ||xmasdom.com^$third-party ||xmlconfig.ltassrv.com^$third-party ||xs.mochiads.com^$third-party ||xtcie.com^$third-party ||xtendadvert.com^$third-party ||xtendmedia.com^$third-party ||xubob.com^$third-party ||xvika.com^$third-party ||xx00.info^$third-party ||xxlink.net^$third-party ||ya88s1yk.com^$third-party ||yabuka.com^$third-party ||yadomedia.com^$third-party ||yambotan.ru^$third-party ||yawnedgtuis.org^$third-party ||yb0t.com^$third-party ||ycasmd.info^$third-party ||yceml.net^$third-party ||yeabble.com^$third-party ||yes-messenger.com^$third-party ||yesadsrv.com^$third-party ||yesnexus.com^$third-party ||yieldads.com^$third-party ||yieldadvert.com^$third-party ||yieldbuild.com^$third-party ||yieldkit.com^$third-party ||yieldlab.net^$third-party ||yieldmanager.com^$third-party ||yieldmanager.net^$third-party ||yieldoptimizer.com^$third-party ||yieldselect.com^$third-party ||yieldx.com^$third-party ||yldbt.com^$third-party ||yldmgrimg.net^$third-party ||yllix.com^$third-party ||ymads.com^$third-party ||yoc-adserver.com^$third-party ||yottacash.com^$third-party ||youcandoitwithroi.com^$third-party ||youlamedia.com^$third-party ||youlouk.com^$third-party ||your-tornado-file.com^$third-party ||your-tornado-file.org^$third-party ||youradexchange.com^$third-party ||yourfastpaydayloans.com^$third-party ||yourquickads.com^$third-party ||ytsa.net^$third-party ||yuarth.com^$third-party ||yucce.com^$third-party ||yumenetworks.com^$third-party ||yvoria.com^$third-party ||yz56lywd.com^$third-party ||yzrnur.com^$third-party ||yzus09by.com^$third-party ||z5x.net^$third-party ||zangocash.com^$third-party ||zanox-affiliate.de^$third-party ||zanox.com^$third-party ||zaparena.com^$third-party ||zappy.co.za^$third-party ||zapunited.com^$third-party ||zde-engage.com^$third-party ||zeads.com^$third-party ||zedo.com^$third-party ||zeesiti.com^$third-party ||zenoviaexchange.com^$third-party ||zenoviagroup.com^$third-party ||zercstas.com^$third-party ||zerezas.com^$third-party ||zferral.com^$third-party ||zidae.com^$third-party ||ziffdavis.com^$third-party ||zipropyl.com^$third-party ||znaptag.com^$third-party ||zoglafi.info^$third-party ||zompmedia.com^$third-party ||zonealta.com^$third-party ||zonplug.com^$third-party ||zoomdirect.com.au^$third-party ||zugo.com^$third-party ||zwaar.org^$third-party ||zxxds.net^$third-party ||zypenetwork.com^$third-party ! Mobile ||adbuddiz.com^$third-party ||adcolony.com^$third-party ||adiquity.com^$third-party ||admob.com^$third-party ||adwhirl.com^$third-party ||adwired.mobi^$third-party ||adzmob.com^$third-party ||airpush.com^$third-party ||amobee.com^$third-party ||appads.com^$third-party ||buxx.mobi^$third-party ||dmg-mobile.com^$third-party ||doubleclick.net^*/pfadx/app.ytpwatch.$third-party ||greystripe.com^$third-party ||inmobi.com^$third-party ||kuad.kusogi.com^$third-party ||mad-adz.com^$third-party ||millennialmedia.com^$third-party ||mkhoj.com^$third-party ||mobgold.com^$third-party ||mobizme.net^$third-party ||mobpartner.mobi^$third-party ||mocean.mobi^$third-party ||mojiva.com^$third-party ||mysearch-online.com^$third-party ||sascdn.com^$third-party ||smaato.net^$third-party ||startappexchange.com^$third-party ||stepkeydo.com^$third-party ||tapjoyads.com^$third-party ||vungle.com^$third-party ||wapdollar.in^$third-party ||waptrick.com^$third-party ||yieldmo.com^$third-party ! Non-English (instead of whitelisting ads) ||adhood.com^$third-party ||atresadvertising.com^$third-party ! Yavli.com ||accmndtion.org^$third-party ||addo-mnton.com^$third-party ||allianrd.net^$third-party ||anomiely.com^$third-party ||appr8.net^$third-party ||artbr.net^$third-party ||baordrid.com^$third-party ||batarsur.com^$third-party ||baungarnr.com^$third-party ||biankord.net^$third-party ||blazwuatr.com^$third-party ||blipi.net^$third-party ||bluazard.net^$third-party ||buhafr.net^$third-party ||casiours.com^$third-party ||chansiar.net^$third-party ||chiuawa.net^$third-party ||chualangry.com^$third-party ||compoter.net^$third-party ||contentolyze.net^$third-party ||contentr.net^$third-party ||crhikay.me^$third-party ||d3lens.com^$third-party ||dilpy.org^$third-party ||domri.net^$third-party ||draugonda.net^$third-party ||drfflt.info^$third-party ||dutolats.net^$third-party ||edabl.net^$third-party ||elepheny.com^$third-party ||entru.co^$third-party ||ergers.net^$third-party ||ershgrst.com^$third-party ||esults.net^$third-party ||exciliburn.com^$third-party ||excolobar.com^$third-party ||exernala.com^$third-party ||extonsuan.com^$third-party ||faunsts.me^$third-party ||flaudnrs.me^$third-party ||flaurse.net^$third-party ||foulsomty.com^$third-party ||fowar.net^$third-party ||frxle.com^$third-party ||frxrydv.com^$third-party ||fuandarst.com^$third-party ||gghfncd.net^$third-party ||gusufrs.me^$third-party ||hapnr.net^$third-party ||havnr.com^$third-party ||heizuanubr.net^$third-party ||hobri.net^$third-party ||hoppr.co^$third-party ||ignup.com^$third-party ||iunbrudy.net^$third-party ||ivism.org^$third-party ||jaspensar.com^$third-party ||jdrm4.com^$third-party ||jellr.net^$third-party ||juruasikr.net^$third-party ||jusukrs.com^$third-party ||kioshow.com^$third-party ||kuangard.net^$third-party ||lesuard.com^$third-party ||lia-ndr.com^$third-party ||lirte.org^$third-party ||loopr.co^$third-party ||nuaknamg.net^$third-party ||oplo.org^$third-party ||opner.co^$third-party ||pikkr.net^$third-party ||polawrg.com^$third-party ||prfffc.info^$third-party ||q3sift.com^$third-party ||qewa33a.com^$third-party ||qzsccm.com^$third-party ||r3seek.com^$third-party ||rdige.com^$third-party ||regersd.net^$third-party ||rhgersf.com^$third-party ||rlex.org^$third-party ||rterdf.me^$third-party ||rugistoto.net^$third-party ||selectr.net^$third-party ||simusangr.com^$third-party ||splazards.com^$third-party ||spoa-soard.com^$third-party ||sxrrxa.net^$third-party ||t3sort.com^$third-party ||th4wwe.net^$third-party ||thrilamd.net^$third-party ||topdi.net^$third-party ||trllxv.co^$third-party ||trndi.net^$third-party ||uppo.co^$third-party ||viewscout.com^$third-party ||vopdi.com^$third-party ||waddr.com^$third-party ||wensdteuy.com^$third-party ||wopdi.com^$third-party ||wuarnurf.net^$third-party ||wuatriser.net^$third-party ||wudr.net^$third-party ||xcrsqg.com^$third-party ||xplrer.co^$third-party ||xylopologyn.com^$third-party ||yardr.net^$third-party ||yobr.net^$third-party ||yodr.net^$third-party ||yomri.net^$third-party ||yopdi.com^$third-party ||ypprr.com^$third-party ||yrrrbn.me^$third-party ||z4pick.com^$third-party ||zomri.net^$third-party ||zrfrornn.net^$third-party ! *** easylist:easylist/easylist_adservers_popup.txt *** ||123vidz.com^$popup,third-party ||1phads.com^$popup,third-party ||32d1d3b9c.se^$popup,third-party ||4dsply.com^$popup,third-party ||5dimes.com^$popup,third-party ||83nsdjqqo1cau183xz.com^$popup,third-party ||888casino.com^$popup,third-party ||888games.com^$popup,third-party ||888media.net^$popup,third-party ||888poker.com^$popup,third-party ||888promos.com^$popup,third-party ||9newstoday.net^$popup,third-party ||abbeyblog.me^$popup,third-party ||ad-apac.doubleclick.net^$popup,third-party ||ad-emea.doubleclick.net^$popup,third-party ||ad-feeds.com^$popup,third-party ||ad.doubleclick.net^$popup,third-party ||ad.zanox.com/ppv/$popup,third-party ||ad131m.com^$popup,third-party ||ad2387.com^$popup,third-party ||ad2games.com^$popup,third-party ||ad4game.com^$popup,third-party ||adbma.com^$popup,third-party ||adcash.com^$popup,third-party ||adfarm.mediaplex.com^$popup,third-party ||adform.net^$popup,third-party ||adimps.com^$popup,third-party ||aditor.com^$popup,third-party ||adjuggler.net^$popup,third-party ||adk2.co^$popup,third-party ||adk2.com^$popup,third-party ||adk2.net^$popup,third-party ||adlure.net^$popup,third-party ||adnxs.com^$popup,third-party ||adonweb.ru^$popup,third-party ||adplxmd.com^$popup,third-party ||ads.sexier.com^$popup,third-party ||adserverplus.com^$popup,third-party ||adshostnet.com^$popup,third-party ||adsmarket.com^$popup,third-party ||adsupply.com^$popup,third-party ||adsurve.com^$popup,third-party ||adtrace.org^$popup,third-party ||adtraffic.org^$popup,third-party ||advertserve.com^$popup,third-party ||advmedialtd.com^$popup,third-party ||affbuzzads.com^$popup,third-party ||aflrm.com^$popup,third-party ||allslotscasino.com^$popup,third-party ||alpinedrct.com^$popup,third-party ||alternads.info^$popup,third-party ||am10.ru^$popup,third-party ||angege.com^$popup,third-party ||annualinternetsurvey.com^$popup,third-party ||answered-questions.com^$popup,third-party ||ar.voicefive.com^$popup,third-party ||awempire.com^$popup,third-party ||awsclic.com^$popup,third-party ||bannerflow.com^$popup,third-party ||baypops.com^$popup,third-party ||becoquin.com^$popup,third-party ||becoquins.net^$popup,third-party ||bentdownload.com^$popup,third-party ||bestproducttesters.com^$popup,third-party ||bidsystem.com^$popup,third-party ||bidvertiser.com^$popup,third-party ||bighot.ru^$popup,third-party ||binaryoptionsgame.com^$popup,third-party ||blinko.es^$popup,third-party ||blinkogold.es^$popup,third-party ||blockthis.es^$popup,third-party ||blogscash.info^$popup,third-party ||bongacams.com^$popup,third-party ||bonzuna.com^$popup,third-party ||brandreachsys.com^$popup,third-party ||bzrvwbsh5o.com^$popup,third-party ||careerjournalonline.com^$popup ||casino.betsson.com^$popup,third-party ||clickmngr.com^$popup,third-party ||clickosmedia.com^$popup,third-party ||clicksor.com^$popup,third-party ||clicksvenue.com^$popup,third-party ||clickter.net^$popup,third-party ||clkads.com^$popup,third-party ||clkmon.com^$popup,third-party ||clkrev.com^$popup,third-party ||cloudtracked.com^$popup,third-party ||cmllk2.info^$popup,third-party ||contentabc.com^$popup,third-party ||cpmstar.com^$popup,third-party ||cpmterra.com^$popup,third-party ||cpvadvertise.com^$popup,third-party ||crazyad.net^$popup,third-party ||directrev.com^$popup,third-party ||distantnews.com^$popup,third-party ||distantstat.com^$popup,third-party ||dojerena.com^$popup,third-party ||doublepimp.com^$popup,third-party ||down1oads.com^$popup,third-party ||downloadboutique.com^$popup,third-party ||downloadthesefile.com^$popup,third-party ||easydownloadnow.com^$popup,third-party ||easykits.org^$popup,third-party ||ebzkswbs78.com^$popup,third-party ||epicgameads.com^$popup,third-party ||euromillionairesystem.me^$popup,third-party ||ewebse.com^$popup,third-party ||exoclick.com^$popup,third-party ||ezdownloadpro.info^$popup,third-party ||f-hookups.com^$popup,third-party ||f-questionnaire.com^$popup,third-party ||fhserve.com^$popup,third-party ||fidel.to^$popup,third-party ||filestube.com^$popup,third-party ||finance-reporting.org^$popup,third-party ||findonlinesurveysforcash.com^$popup,third-party ||firstclass-download.com^$popup,third-party ||firstmediahub.com^$popup,third-party ||fmdwbsfxf0.com^$popup,third-party ||friendlyduck.com^$popup,third-party ||g05.info^$popup,third-party ||ganja.com^$popup,third-party ||gofindmedia.net^$popup,third-party ||googleads.g.doubleclick.net^$popup,third-party ||gotoplaymillion.com^$popup,third-party ||greatbranddeals.com^$popup,third-party ||gsniper2.com^$popup,third-party ||hd-plugin.com^$popup,third-party ||highcpms.com^$popup,third-party ||homecareerforyou1.info^$popup,third-party ||hornygirlsexposed.com^$popup,third-party ||hotchatdirect.com^$popup,third-party ||hstpnetwork.com^$popup,third-party ||iiasdomk1m9812m4z3.com^$popup,third-party ||ilividnewtab.com^$popup,third-party ||inbinaryoption.com^$popup,third-party ||indianmasala.com^$popup,third-party,domain=masalaboard.com ||indianweeklynews.com^$popup,third-party ||insta-cash.net^$popup,third-party ||instantpaydaynetwork.com^$popup,third-party ||jdtracker.com^$popup,third-party ||jujzh9va.com^$popup,third-party ||junbi-tracker.com^$popup,third-party ||kanoodle.com^$popup,third-party ||landsraad.cc^$popup,third-party ||legisland.net^$popup,third-party ||ligatus.com^$popup,third-party ||livechatflirt.com^$popup,third-party ||livepromotools.com^$popup,third-party ||liversely.net^$popup,third-party ||lmebxwbsno.com^$popup,third-party ||lnkgt.com^$popup,third-party ||m57ku6sm.com^$popup,third-party ||marketresearchglobal.com^$popup,third-party ||media-app.com^$popup,third-party ||media-servers.net^$popup,third-party ||mediaseeding.com^$popup,third-party ||meetgoodgirls.com^$popup,third-party ||meetsexygirls.org^$popup,third-party ||menepe.com^$popup,third-party ||metodoroleta24h.com^$popup,third-party ||millionairesurveys.com^$popup,third-party ||mktmobi.com^$popup,third-party ||mobileraffles.com^$popup,third-party ||moneytec.com^$popup,third-party ||my-layer.net^$popup,third-party ||n388hkxg.com^$popup,third-party ||netliker.com^$popup,third-party ||nturveev.com^$popup,third-party ||nymphdate.com^$popup,third-party ||onad.eu^$popup,third-party ||onclickads.net^$popup,third-party ||onhitads.net^$popup,third-party ||onlinecareerpackage.com^$popup,third-party ||onlinecashmethod.com^$popup,third-party ||open-downloads.net^$popup,third-party ||openadserving.com^$popup,third-party ||overturs.com^$popup,third-party ||partypills.org^$popup,third-party ||pdfcomplete.com^$popup,third-party ||perfcreatives.com^$popup,third-party ||pexu.com^$popup,third-party ||pgmediaserve.com^$popup,third-party ||pipaoffers.com^$popup,third-party ||pointroll.com^$popup,third-party ||popads.net^$popup,third-party ||popmyads.com^$popup,third-party ||print3.info^$popup,third-party ||prizegiveaway.org^$popup,third-party ||promotions-paradise.org^$popup,third-party ||promotions.sportsbet.com.au^$popup,third-party ||propellerads.com^$popup,third-party ||propellerpops.com^$popup,third-party ||prowlerz.com^$popup,third-party ||pubads.g.doubleclick.net^$popup,third-party ||pubdirecte.com^$popup,third-party ||pulse360.com^$popup,third-party ||raoplenort.biz^$popup,third-party ||ratari.ru^$popup,third-party ||rdsrv.com^$popup,third-party ||rehok.km.ua^$popup,third-party ||rgadvert.com^$popup,third-party ||rikhov.ru^$popup,third-party ||ringtonepartner.com^$popup,third-party ||ronetu.ru^$popup,third-party ||roulettebotplus.com^$popup,third-party ||rubikon6.if.ua^$popup,third-party ||secureintl.com^$popup,third-party ||senzapudore.it^$popup,third-party ||serving-sys.com^$popup,third-party ||sexitnow.com^$popup,third-party ||silstavo.com^$popup,third-party ||simpleinternetupdate.com^$popup,third-party ||singlesexdates.com^$popup,third-party ||slimspots.com^$popup,third-party ||smartwebads.com^$popup,third-party ||sms-mmm.com^$popup,third-party ||smutty.com^$popup,third-party ||sparkstudios.com^$popup,third-party ||srv-ad.com^$popup,third-party ||srv2trking.com^$popup,third-party ||srvpub.com^$popup,third-party ||statstrackeronline.com^$popup,third-party ||surveyend.com^$popup,third-party ||surveysforgifts.org^$popup,third-party ||surveyspaid.com^$popup,third-party ||surveystope.com^$popup,third-party ||swadvertising.org^$popup,third-party ||symkashop.ru^$popup,third-party ||syncedvision.com^$popup,third-party ||technicssurveys.info^$popup,third-party ||textsrv.com^$popup,third-party ||the-consumer-reporter.org^$popup,third-party ||therewardsurvey.com^$popup,third-party ||topshelftraffic.com^$popup,third-party ||toroadvertisingmedia.com^$popup,third-party ||totrack.ru^$popup,third-party ||trafficforce.com^$popup,third-party ||traffichaus.com^$popup,third-party ||trklnks.com^$popup,third-party ||trw12.com^$popup,third-party ||tutvp.com^$popup,third-party ||updater-checker.net^$popup,third-party ||vgsgaming-ads.com^$popup,third-party ||vipcpms.com^$popup,third-party ||vprmnwbskk.com^$popup,third-party ||w4statistics.info^$popup,third-party ||wahoha.com^$popup,third-party ||wbsadsdel.com^$popup,third-party ||wbsadsdel2.com^$popup,third-party ||weareheard.org^$popup,third-party ||websearchers.net^$popup,third-party ||webtrackerplus.com^$popup,third-party ||weliketofuckstrangers.com^$popup,third-party ||wigetmedia.com^$popup,third-party ||wonderlandads.com^$popup,third-party ||worldrewardcenter.net^$popup,third-party ||wwwpromoter.com^$popup,third-party ||wzus1.ask.com^$popup,third-party ||xclicks.net^$popup,third-party ||xtendmedia.com^$popup,third-party ||yieldmanager.com^$popup,third-party ||yieldtraffic.com^$popup,third-party ||yupiromo.ru^$popup,third-party ||z5x.net^$popup,third-party ||zedo.com^$popup,third-party ! *** easylist:easylist_adult/adult_adservers.txt *** ||0llii0g6.com^$third-party ||100pour.com^$third-party ||10y5gehv.com^$third-party ||123advertising.nl^$third-party ||15yomodels.com^$third-party ||173.245.86.115^$domain=~yobt.com.ip ||18naked.com^$third-party ||195.228.74.26^$third-party ||1loop.com^$third-party ||1tizer.com^$third-party ||206.217.206.137^$third-party ||212.150.34.117^$third-party ||21sexturycash.com^$third-party ||247teencash.net^$third-party ||24smile.org^$third-party ||24x7adservice.com^$third-party ||33traffic.com^$third-party ||40xbfzk8.com^$third-party ||45i73jv6.com^$third-party ||4link.it^$third-party ||59zs1xei.com^$third-party ||699fy4ne.com^$third-party ||750industries.com^$third-party ||76.76.5.113^$third-party ||777-partner.com^$third-party ||777-partner.net^$third-party ||777-partners.com^$third-party ||777-partners.net^$third-party ||777partner.com^$third-party ||777partner.net^$third-party ||7cxcrejm.com^$third-party ||7vws1j1j.com^$third-party ||80.77.113.200^$third-party ||85.17.210.202^$third-party ||89.248.172.46^$third-party ||8ipztcc1.com^$third-party ||aaovn.info^$third-party ||abakys.ru^$third-party ||abusedbabysitters.com^$third-party ||acmexxx.com^$third-party ||acnescarsx.info^$third-party ||actionlocker.com^$third-party ||ad-411.com^$third-party ||ad-u.com^$third-party ||ad001.ru^$third-party ||ad4partners.com^$third-party ||adbars.net^$third-party ||adcell.de^$third-party ||addbags.com^$third-party ||adfux.com^$third-party ||adjunky.com^$third-party ||admez.com^$third-party ||adnetxchange.com^$third-party ||adparad.net^$third-party ||adperiun.com^$third-party ||adpron.com^$third-party ||adrent.net^$third-party ||adsbr.info^$third-party ||adsgangsta.com^$third-party ||adshostview.com^$third-party ||adskape.ru^$third-party ||adsyst.biz^$third-party ||adult3dcomics.com^$third-party ||adultaccessnow.com^$third-party ||adultadmedia.com^$third-party ||adultadvertising.net^$third-party ||adultcommercial.net^$third-party ||adultdatingtraffic.com^$third-party ||adultlinkexchange.com^$third-party ||adultmediabuying.com^$third-party ||adultmoviegroup.com^$third-party ||adultoafiliados.com.br^$third-party ||adultpopunders.com^$third-party ||adultsense.com^$third-party ||adultsense.org^$third-party ||adulttiz.com^$third-party ||adulttubetraffic.com^$third-party ||adv-plus.com^$third-party ||adv777.com^$third-party ||adventory.com^$third-party ||advertisingsex.com^$third-party ||advertom.com^$third-party ||advertrtb.com^$third-party ||advmaker.ru^$third-party ||advmania.com^$third-party ||advprotraffic.com^$third-party ||advredir.com^$third-party ||advsense.info^$third-party ||adxite.com^$third-party ||adxmarket.com^$third-party ||adxpansion.com^$third-party ||adxregie.com^$third-party ||adzs.com^$third-party ||aeesy.com^$third-party ||affiliatewindow.com^$third-party ||affiliation-int.com^$third-party ||affiligay.net^$third-party ||aipbannerx.com^$third-party ||aipmedia.com^$third-party ||alfatraffic.com^$third-party ||all-about-tech.com^$third-party ||alladultcash.com^$third-party ||allosponsor.com^$third-party ||allotraffic.com^$third-party ||amtracking01.com^$third-party ||amvotes.ru^$third-party ||anastasia-international.com^$third-party ||angelpastel.com^$third-party ||antaraimedia.com^$third-party ||antoball.com^$third-party ||apromoweb.com^$third-party ||asiafriendfinder.com^$third-party ||augrenso.com^$third-party ||awmcenter.eu^$third-party ||awmpartners.com^$third-party ||ax47mp-xp-21.com^$third-party ||azerbazer.com^$third-party ||aztecash.com^$third-party ||basesclick.ru^$third-party ||baskodenta.com^$third-party ||bcash4you.com^$third-party ||belamicash.com^$third-party ||belasninfetas.org^$third-party ||bestholly.com^$third-party ||bestssn.com^$third-party ||betweendigital.com^$third-party ||bgmtracker.com^$third-party ||biksibo.ru^$third-party ||black-ghettos.info^$third-party ||blossoms.com^$third-party ||board-books.com^$third-party ||boinkcash.com^$third-party ||bookofsex.com^$third-party ||branzas.com^$third-party ||brightcpm.net^$third-party ||brothersincash.com^$third-party ||brqvld0p.com^$third-party ||bumblecash.com^$third-party ||bumskontakte.ch^$third-party ||cache.imagehost123.com^$third-party ||cam-lolita.net^$third-party ||cam4flat.com^$third-party ||camads.net^$third-party ||camcrush.com^$third-party ||camdough.com^$third-party ||camduty.com^$third-party ||campartner.com^$third-party ||camprime.com^$third-party ||campromos.nl^$third-party ||camsense.com^$third-party ||camsitecash.com^$third-party ||camzap.com^$third-party ||cash-program.com^$third-party ||cash4movie.com^$third-party ||cashlayer.com^$third-party ||cashthat.com^$third-party ||cashtraff.com^$third-party ||cdn.nsimg.net^$third-party ||ceepq.com^$third-party ||celeb-ads.com^$third-party ||celogera.com^$third-party ||cennter.com^$third-party ||certified-apps.com^$third-party ||cervicalknowledge.info^$third-party ||chatischat.com^$third-party ||che-ka.com^$third-party ||chestyry.com^$third-party ||chopstick16.com^$third-party ||citysex.com^$third-party ||clearac.com^$third-party ||clickganic.com^$third-party ||clickpapa.com^$third-party ||clicksvenue.com^$third-party ||clickthruserver.com^$third-party ||clicktrace.info^$third-party ||cmdfnow.com^$third-party ||codelnet.com^$third-party ||coldhardcash.com^$third-party ||coloredguitar.com^$third-party ||colpory.com^$third-party ||comunicazio.com^$third-party ||cpacoreg.com^$third-party ||cpl1.ru^$third-party ||crakbanner.com^$third-party ||crakcash.com^$third-party ||creoads.com^$third-party ||crocoads.com^$third-party ||crtracklink.com^$third-party ||cwgads.com^$third-party ||cyberbidhost.com^$third-party ||cybernetentertainment.com^$third-party ||d0main.ru^$third-party ||d29gqcij.com^$third-party ||daffaite.com^$third-party ||dallavel.com^$third-party ||dana123.com^$third-party ||danzabucks.com^$third-party ||darangi.ru^$third-party ||data-ero-advertising.com^$third-party ||datefunclub.com^$third-party ||datetraders.com^$third-party ||datexchanges.net^$third-party ||dating-adv.com^$third-party ||datingadnetwork.com^$third-party ||datingamateurs.com^$third-party ||datingidol.com^$third-party ||dblpmp.com^$third-party ||deecash.com^$third-party ||demanier.com^$third-party ||denotyro.com^$third-party ||depilflash.tv^$third-party ||depravedwhores.com^$third-party ||desiad.net^$third-party ||digitaldesire.com^$third-party ||directadvert.ru^$third-party ||directchat.tv^$third-party ||direction-x.com^$third-party ||discreetlocalgirls.com^$third-party ||divascam.com^$third-party ||divertura.com^$third-party ||dofolo.ru^$third-party ||dosugcz.biz^$third-party ||double-check.com^$third-party ||doublegear.com^$third-party ||drevil.to^$third-party ||dro4icho.ru^$third-party ||dtiserv2.com^$third-party ||dvdkinoteatr.com^$third-party ||eadulttraffic.com^$third-party ||easy-dating.org^$third-party ||easyflirt.com^$third-party ||ebdr2.com^$third-party ||elekted.com^$third-party ||eltepo.ru^$third-party ||emediawebs.com^$third-party ||enoratraffic.com^$third-party ||eragi.ru^$third-party ||erosadv.com^$third-party ||erotikdating.com^$third-party ||erotizer.info^$third-party ||escortso.com^$third-party ||eu2xml.com^$third-party ||euro-rx.com^$third-party ||euro4ads.de^$third-party ||exchangecash.de^$third-party ||exclusivepussy.com^$third-party ||exoclickz.com^$third-party ||exogripper.com^$third-party ||eyemedias.com^$third-party ||facebookofsex.com^$third-party ||faceporn.com^$third-party ||facetz.net^$third-party ||fanmalinin.ru^$third-party ||feeder.xxx^$third-party ||felixflow.com^$third-party ||fickads.net^$third-party ||filthads.com^$third-party ||findandtry.com^$third-party ||flashadtools.com^$third-party ||fleshcash.com^$third-party ||fleshlightgirls.com^$third-party ||flipflapflo.info^$third-party ||flipflapflo.net^$third-party ||flirt4e.com^$third-party ||flirt4free.com^$third-party ||flirtingsms.com^$third-party ||fmscash.com^$third-party ||fncash.com^$third-party ||forgetstore.com^$third-party ||freakads.com^$third-party ||free-porn-vidz.com^$third-party ||frestacero.com^$third-party ||frestime.com^$third-party ||frivol-ads.com^$third-party ||frutrun.com^$third-party ||fuckbook.cm^$third-party ||fuckbookdating.com^$third-party ||fuckermedia.com^$third-party ||fuckyoucash.com^$third-party ||fuelbuck.com^$third-party ||funcel.mobi^$third-party ||funnypickuplinesforgirls.com^$third-party ||g6ni40i7.com^$third-party ||g726n8cy.com^$third-party ||gamblespot.ru^$third-party ||ganardineroreal.com^$third-party ||gayadpros.com^$third-party ||gayxperience.com^$third-party ||gefnaro.com^$third-party ||genialradio.com^$third-party ||geoaddicted.net^$third-party ||geofamily.ru^$third-party ||geoinventory.com^$third-party ||getiton.com^$third-party ||gfhdkse.com^$third-party ||ggwcash.com^$third-party ||gl-cash.com^$third-party ||glbtrk.com^$third-party ||go2euroshop.com^$third-party ||goallurl.ru^$third-party ||goklics.ru^$third-party ||golderotica.com^$third-party ||govereign.com^$third-party ||greatcpm.com^$third-party ||gridlockparadise.com^$third-party ||gtsads.com^$third-party ||gunzblazingpromo.com^$third-party ||helltraffic.com^$third-party ||hentaibiz.com^$third-party ||herezera.com^$third-party ||hiddenbucks.com^$third-party ||highnets.com^$third-party ||hipals.com^$third-party ||hizlireklam.com^$third-party ||home-soon.com^$third-party ||hookupbucks.com^$third-party ||hopilos.com^$third-party ||hornymatches.com^$third-party ||hornyspots.com^$third-party ||host-go.info^$third-party ||hostave4.net^$third-party ||hot-dances.com^$third-party ||hot-socials.com^$third-party ||hotsocials.com^$third-party ||hsmclick.com^$third-party ||hubtraffic.com^$third-party ||icetraffic.com^$third-party ||icqadvert.org^$third-party ||ideal-sexe.com^$third-party ||idolbucks.com^$third-party ||igiplay.net^$third-party ||iheartbucks.com^$third-party ||ilovecheating.com^$third-party ||impotencehelp.info^$third-party ||inheart.ru^$third-party ||intellichatadult.com^$third-party ||internebula.net^$third-party ||intrapromotion.com^$third-party ||iprofit.cc^$third-party ||itmcash.com^$third-party ||itrxx.com^$third-party ||itslive.com^$third-party ||itw.me^$third-party ||iwinnersadvantage.com^$third-party ||ixspublic.com^$third-party ||jackao.net^$third-party ||javbucks.com^$third-party ||jaymancash.com^$third-party ||jerrcotch.com^$third-party ||jfresi.com^$third-party ||joinnowinstantly.com^$third-party ||jowapt.com^$third-party ||joyourself.com^$third-party ||juicyads.com^$third-party ||juicycash.net^$third-party ||justresa.com^$third-party ||jz9ugaqb.com^$third-party ||k9x.net^$third-party ||kadam.ru^$third-party ||kaplay.com^$third-party ||kingpinmedia.net^$third-party ||kinopokaz.org^$third-party ||kliklink.ru^$third-party ||kolestence.com^$third-party ||kolitat.com^$third-party ||kolort.ru^$third-party ||kuhnivsemisrazu.ru^$third-party ||kwot.biz^$third-party ||lavantat.com^$third-party ||leche69.com^$third-party ||legendarylars.com^$third-party ||lickbylick.com^$third-party ||lifepromo.biz^$third-party ||limon.biz^$third-party ||links-and-traffic.com^$third-party ||livecam.com^$third-party ||livejasmin.tv^$third-party ||liveprivates.com^$third-party ||livepromotools.com^$third-party ||livetraf.com^$third-party ||lizads.com^$third-party ||loa-traffic.com^$third-party ||loading-delivery1.com^$third-party ||lostun.com^$third-party ||loveadverts.com^$third-party ||lovecam.com.br^$third-party ||lovercash.com^$third-party ||lsawards.com^$third-party ||lucidcommerce.com^$third-party ||luvcash.com^$third-party ||luvcom.com^$third-party ||madbanner.com^$third-party ||magical-sky.com^$third-party ||mahnatka.ru^$third-party ||mallcom.com^$third-party ||mallorcash.com^$third-party ||manfys.com^$third-party ||markswebcams.com^$third-party ||masterwanker.com^$third-party ||matrimoniale3x.ro^$third-party ||matrix-cash.com^$third-party ||maxcash.com^$third-party ||maxiadv.com^$third-party ||mb103.com^$third-party ||mc-nudes.com^$third-party ||mdlsrv.com^$third-party ||meccahoo.com^$third-party ||media-click.ru^$third-party ||mediagra.com^$third-party ||mediumpimpin.com^$third-party ||megoads.eu^$third-party ||meineserver.com^$third-party ||menteret.com^$third-party ||meta4-group.com^$third-party ||methodcash.com^$third-party ||meubonus.com^$third-party ||might-stay.info^$third-party ||millioncash.ru^$third-party ||mmaaxx.com^$third-party ||mo8mwxi1.com^$third-party ||mobalives.com^$third-party ||mobbobr.com^$third-party ||mobilerevenu.com^$third-party ||mopilod.com^$third-party ||morehitserver.com^$third-party ||mp3vicio.com^$third-party ||mpmcash.com^$third-party ||mrskincash.com^$third-party ||msquaredproductions.com^$third-party ||mtoor.com^$third-party ||mtree.com^$third-party ||myadultbanners.com^$third-party ||mymirror.biz^$third-party ||myprecisionads.com^$third-party ||mywebclick.net^$third-party ||n9nedegrees.com^$third-party ||nastydollars.com^$third-party ||nature-friend.com^$third-party ||netosdesalim.info^$third-party ||neuesdate.com^$third-party ||newads.bangbros.com^$third-party ||newagerevenue.com^$third-party ||newnudecash.com^$third-party ||newsexbook.com^$third-party ||ngbn.net^$third-party ||nikkiscash.com^$third-party ||ningme.ru^$third-party ||njmaq.com^$third-party ||nkk31jjp.com^$third-party ||nscash.com^$third-party ||nsfwads.com^$third-party ||nummobile.com^$third-party ||nvp2auf5.com^$third-party ||oddads.net^$third-party ||odzb5nkp.com^$third-party ||okeo.ru^$third-party ||onhercam.com^$third-party ||onyarysh.ru^$third-party ||ordermc.com^$third-party ||orodi.ru^$third-party ||otaserve.net^$third-party ||otherprofit.com^$third-party ||outster.com^$third-party ||owlopadjet.info^$third-party ||owpawuk.ru^$third-party ||ozelmedikal.com^$third-party ||ozon.ru^$third-party ||ozone.ru^$third-party,domain=~ozon.ru|~ozonru.co.il|~ozonru.com|~ozonru.eu|~ozonru.kz ||ozonru.eu^$third-party ||paid-to-promote.net^$third-party ||parkingpremium.com^$third-party ||partnercash.com^$third-party ||partnercash.de^$third-party ||pecash.com^$third-party ||pepipo.com^$third-party ||philstraffic.com^$third-party ||pictureturn.com^$third-party ||pinkhoneypots.com^$third-party ||plachetde.biz^$third-party ||plantaosexy.com^$third-party ||plugrush.com^$third-party ||pnads.com^$third-party ||polimantu.com^$third-party ||poonproscash.com^$third-party ||pop-bazar.net^$third-party ||popander.biz^$third-party ||popander.com^$third-party ||popdown.biz^$third-party ||poppcheck.de^$third-party ||popupclick.ru^$third-party ||porkolt.com^$third-party ||porn-ad.org^$third-party ||porn-hitz.com^$third-party ||porn-site-builder.com^$third-party ||porn88.net^$third-party ||porn99.net^$third-party ||pornattitude.com^$third-party ||pornconversions.com^$third-party ||pornearn.com^$third-party ||pornkings.com^$third-party ||pornleep.com^$third-party ||porno-file.ru^$third-party ||pornoow.com^$third-party ||porntrack.com^$third-party ||portable-basketball.com^$third-party ||pourmajeurs.com^$third-party ||ppc-direct.com^$third-party ||premature-ejaculation-causes.org^$third-party ||premiumhdv.com^$third-party ||privacyprotector.com^$third-party ||private4.com^$third-party ||privateseiten.net^$third-party ||privatewebseiten.com^$third-party ||profistats.net^$third-party ||profitstat.biz^$third-party ||program3.com^$third-party ||promo4partners.com^$third-party ||promocionesweb.com^$third-party ||promotion-campaigns.com^$third-party ||promotools.biz^$third-party ||promowebstar.com^$third-party ||protect-x.com^$third-party ||protizer.ru^$third-party ||prscripts.com^$third-party ||ptclassic.com^$third-party ||ptrfc.com^$third-party ||ptwebcams.com^$third-party ||publish4.com^$third-party ||pussyeatingclub.com^$third-party ||pussyeatingclubcams.com^$third-party ||putags.com^$third-party ||putanapartners.com^$third-party ||pyiel2bz.com^$third-party ||quagodex.com^$third-party ||queronamoro.com^$third-party ||quexotac.com^$third-party ||r7e0zhv8.com^$third-party ||rack-media.com^$third-party ||ragazzeinvendita.com^$third-party ||ramctrlgate.com^$third-party ||rareru.ru^$third-party ||reachword.com^$third-party ||real2clean.ru^$third-party ||realdatechat.com^$third-party ||realitycash.com^$third-party ||realitytraffic.com^$third-party ||redcash.net^$third-party ||redirectoptimizer.com^$third-party ||redlightcenter.com^$third-party ||redpineapplemedia.com^$third-party ||reliablebanners.com^$third-party ||reprak.com^$third-party ||retargetpro.net^$third-party ||retoxo.com^$third-party ||rexbucks.com^$third-party ||rivcash.com^$third-party ||rmbn.net^$third-party ||rmkflouh.com^$third-party ||robotadserver.com^$third-party ||royal-cash.com^$third-party ||rsdisp.ru^$third-party ||rtbsystem.com^$third-party ||rubanners.com^$third-party ||rukplaza.com^$third-party ||rulerclick.com^$third-party ||rulerclick.ru^$third-party ||runetki.co^$third-party ||runetki.com^$third-party ||russianlovematch.com^$third-party ||safelinktracker.com^$third-party ||sancdn.net^$third-party ||sascentral.com^$third-party ||sbs-ad.com^$third-party ||scenesgirls.com^$third-party ||searchpeack.com^$third-party ||searchx.eu^$third-party ||secretbehindporn.com^$third-party ||seekbang.com^$third-party ||seemybucks.com^$third-party ||seitentipp.com^$third-party ||senkinar.com^$third-party ||sesxc.com^$third-party ||sexad.net^$third-party ||sexdatecash.com^$third-party ||sexlist.com^$third-party ||sexole.com^$third-party ||sexopages.com^$third-party ||sexplaycam.com^$third-party ||sexsearch.com^$third-party ||sextracker.com^$third-party ||sextubecash.com^$third-party ||sexvertise.com^$third-party ||sexy-ch.com^$third-party ||sexypower.net^$third-party ||shopping-centres.org^$third-party ||siccash.com^$third-party ||sixsigmatraffic.com^$third-party ||sjosteras.com^$third-party ||skeettools.com^$third-party ||slendastic.com^$third-party ||smartbn.ru^$third-party ||sms-xxx.com^$third-party ||smutty.com^$third-party ||socialsexnetwork.net^$third-party ||solutionsadultes.com^$third-party ||spcwm.com^$third-party ||spunkycash.com^$third-party ||squeeder.com^$third-party ||startede.com^$third-party ||startwebpromo.com^$third-party ||stat-data.net^$third-party ||steamtraffic.com^$third-party ||sterrencash.nl^$third-party ||streamateaccess.com^$third-party ||stripsaver.com^$third-party ||sunnysmedia.com^$third-party ||sv2.biz^$third-party ||sweetmedia.org^$third-party ||sweetstudents.com^$third-party ||talk-blog.com^$third-party ||targetingnow.com^$third-party ||targettrafficmarketing.net^$third-party ||tarkita.ru^$third-party ||teasernet.ru^$third-party ||teaservizio.com^$third-party ||tech-board.com^$third-party ||teendestruction.com^$third-party ||the-adult-company.com^$third-party ||thebunsenburner.com^$third-party ||thepayporn.com^$third-party ||thesocialsexnetwork.com^$third-party ||thumbnail-galleries.net^$third-party ||timteen.com^$third-party ||tingrinter.com^$third-party ||tinyweene.com^$third-party ||titsbro.net^$third-party ||titsbro.org^$third-party ||titsbro.pw^$third-party ||tizernet.com^$third-party ||tkhigh.com^$third-party ||tm-core.net^$third-party ||tmserver-1.com^$third-party ||tmserver-2.net^$third-party ||todayssn.com^$third-party ||toget.ru^$third-party ||top-sponsor.com^$third-party ||topbucks.com^$third-party ||tossoffads.com^$third-party ||tracelive.ru^$third-party ||tracker2kss.eu^$third-party ||trackerodss.eu^$third-party ||traffbiz.ru^$third-party ||traffic-in.com^$third-party ||traffic.ru^$third-party ||trafficholder.com^$third-party ||traffichunt.com^$third-party ||trafficlearn.com^$third-party ||trafficpimps.com^$third-party ||trafficshop.com^$third-party ||trafficstars.com^$third-party ||trafficundercontrol.com^$third-party ||traficmax.fr^$third-party ||trafogon.net^$third-party ||transexy.it^$third-party ||trustedadserver.com^$third-party ||trw12.com^$third-party ||try9.com^$third-party ||ttlmodels.com^$third-party ||tubeadnetwork.com^$third-party ||tubedspots.com^$third-party ||tufosex.com.br^$third-party ||tvzavr.ru^$third-party ||twistyscash.com^$third-party ||ukreggae.ru^$third-party ||unaspajas.com^$third-party ||unlimedia.net^$third-party ||uxernab.com^$third-party ||ver-pelis.net^$third-party ||verticalaffiliation.com^$third-party ||video-people.com^$third-party ||virtuagirlhd.com^$third-party ||vividcash.com^$third-party ||vktr073.net^$third-party ||vlexokrako.com^$third-party ||vlogexpert.com^$third-party ||vod-cash.com^$third-party ||vogopita.com^$third-party ||vogorana.ru^$third-party ||vroll.net^$third-party ||vrstage.com^$third-party ||walprater.com^$third-party ||wamcash.com^$third-party ||warsomnet.com^$third-party ||webcambait.com^$third-party ||webcampromotions.com^$third-party ||webclickengine.com^$third-party ||webclickmanager.com^$third-party ||websitepromoserver.com^$third-party ||webstats.com.br^$third-party ||webteaser.ru^$third-party ||weownthetraffic.com^$third-party ||weselltraffic.com^$third-party ||wetpeachcash.com^$third-party ||whaleads.com^$third-party ||wifelovers.com^$third-party ||wildhookups.com^$third-party ||wildmatch.com^$third-party ||wood-pen.com^$third-party ||worldsbestcams.com^$third-party ||wwwmobiroll.com^$third-party ||x-adservice.com^$third-party ||x-exchanger.co.uk^$third-party ||x3v66zlz.com^$third-party ||xclickdirect.com^$third-party ||xclicks.net^$third-party ||xfuckbook.com^$third-party ||xhamstercams.com^$third-party ||xidx.org^$third-party ||xlovecam.com^$third-party ||xmediawebs.net^$third-party ||xoliter.com^$third-party ||xpollo.com^$third-party ||xpop.co^$third-party ||xxltr.com^$third-party ||xxxallaccesspass.com^$third-party ||xxxbannerswap.com^$third-party ||xxxblackbook.com^$third-party ||xxxex.com^$third-party ||xxxlnk.com^$third-party ||xxxmatch.com^$third-party ||xxxvipporno.com^$third-party ||xxxwebtraffic.com^$third-party ||y72yuyr9.com^$third-party ||yazcash.com^$third-party ||yesmessenger.com^$third-party ||yfum.com^$third-party ||yobihost.com^$third-party ||yoshatia.com^$third-party ||your-big.com^$third-party ||yourdatelink.com^$third-party ||yourfuckbook.com^$third-party,domain=~fuckbookhookups.com ||ypmadserver.com^$third-party ||yu0123456.com^$third-party ||yuppads.com^$third-party ||yx0banners.com^$third-party ||zinzimo.info^$third-party ||ziphentai.com^$third-party ! Mobile ||reporo.net^$third-party ! *** easylist:easylist_adult/adult_adservers_popup.txt *** ||33traffic.com^$popup ||3file.info^$popup,third-party ||3questionsgetthegirl.com^$popup ||45i73jv6.com^$popup,third-party ||adtgs.com^$popup ||adultadmedia.com^$popup,third-party ||adultadworld.com^$popup,third-party ||adultmoda.com^$popup,third-party ||adxite.com^$popup,third-party ||adxpansion.com^$popup,third-party ||banners.cams.com^$popup,third-party ||bitterstrawberry.com^$popup ||buy404s.com^$popup ||c4tracking01.com^$popup,third-party ||chokertraffic.com^$popup,third-party ||chtic.net^$popup,third-party ||doublegear.com^$popup,third-party ||dverser.ru^$popup,third-party ||easysexdate.com^$popup ||ebocornac.com^$popup,third-party ||ekod.info^$popup,third-party ||ero-advertising.com^$popup,third-party ||everyporn.net^$popup,third-party ||exgfpunished.com^$popup,third-party ||exogripper.com^$popup ||fbay.tv^$popup ||filthads.com^$popup,third-party ||flagads.net^$popup ||foaks.com^$popup,third-party ||fox-forden.ru^$popup,third-party ||fpctraffic2.com^$popup,third-party ||freecamsexposed.com^$popup ||freewebcams.com^$popup,third-party ||gothot.org^$popup,third-party ||hanaprop.com^$popup,third-party ||hapend.biz^$popup,third-party ||herezera.com^$popup ||hizlireklam.com^$popup,third-party ||hornymatches.com^$popup,third-party ||imagesnake.com^$popup,third-party ||imgcarry.com^$popup,third-party ||indianfriendfinder.com^$popup,third-party ||ipvertising.com^$popup ||juicyads.com^$popup,third-party ||kaizentraffic.com^$popup,third-party ||legacyminerals.net^$popup,third-party ||loltrk.com^$popup,third-party ||naughtyplayful.com^$popup,third-party ||needlive.com^$popup ||njmaq.com^$popup,third-party ||pinkberrytube.com^$popup ||playgirl.com^$popup ||plinx.net^$popup,third-party ||plugrush.com^$popup,third-party ||popcash.net^$popup,third-party ||pornbus.org^$popup ||prexista.com^$popup,third-party ||prpops.com^$popup,third-party ||reviewdollars.com^$popup,third-party ||sascentral.com^$popup,third-party ||setravieso.com^$popup,third-party ||sex-journey.com^$popup,third-party ||sexad.net^$popup,third-party ||sexflirtbook.com^$popup,third-party ||sexintheuk.com^$popup,third-party ||socialsex.biz^$popup,third-party ||socialsex.com^$popup,third-party ||targetingnow.com^$popup,third-party ||trafficbroker.com^$popup ||trafficholder.com^$popup,third-party ||trafficstars.com^$popup ||vlexokrako.com^$popup ||voyeurbase.com^$popup,third-party ||watchmygf.com^$popup ||xdtraffic.com^$popup,third-party ||xmatch.com^$popup ||xpeeps.com^$popup,third-party ||xvika.com^$popup,third-party ||xvika.net^$popup,third-party ||xxxbunker.com^$popup,third-party ||xxxmatch.com^$popup ||y72yuyr9.com^$popup,third-party !-----------------------------Third-party adverts-----------------------------! ! *** easylist:easylist/easylist_thirdparty.txt *** -api.adyoulike.com ||000webhost.com/images/banners/ ||04stream.com/pop*.js ||1-million-usd.com/images/banners/ ||108.166.93.81/rotate/$domain=~infowars.com.ip ||109.201.134.110^$domain=04stream.com ||110.45.173.103/ad/$third-party ||110mb.com/images/banners/ ||12dayswidget.com/widgets/ ||173.199.120.7/delivery/$domain=~p2p.adserver.ip ||173.225.186.54^$third-party,domain=~apps.su.ip ||178.238.233.242/open.js ||1page.co.za/affiliate/ ||1stag.com/main/img/banners/ ||1whois.org/static/popup.js ||208.43.84.120/trueswordsa3.gif$third-party,domain=~trueswords.com.ip ||209.15.224.6^$third-party,domain=~liverail-mlgtv.ip ||216.41.211.36/widget/$third-party,domain=~bpaww.com.ip ||217.115.147.241/media/$third-party,domain=~elb-kind.de.ip ||24.com//flashplayer/ova-jw.swf$object-subrequest ||247hd.net/ad| ||24casino.cz/poker300-$third-party ||24hrlikes.com/images/$third-party ||2beon.co.kr/nad/$third-party ||2leep.com/ticker2/$third-party ||2yu.in/banner/$third-party ||360pal.com/ads/$third-party ||3dots.co.il/pop/ ||4getlikes.com/promo/ ||69.50.226.158^$third-party,domain=~worth1000.com.ip ||6angebot.ch^$third-party,domain=netload.in ||6theory.com/pub/ ||770.com/banniere.php? ||80.94.76.4/abd.php? ||95.131.238.35^$third-party,domain=~maltatoday.mt.ip ||96.9.176.245^$third-party ||a.livesportmedia.eu^ ||a.ucoz.net^ ||a.watershed-publishing.com^ ||a04296f070c0146f314d-0dcad72565cb350972beb3666a86f246.r50.cf5.rackcdn.com^ ||a1channel.net/img/downloadbtn2.png ||a1channel.net/img/watch_now.gif ||abacast.com/banner/ ||ablacrack.com/popup-pvd.js$third-party ||ad.23blogs.com^$third-party ||ad.about.co.kr^ ||ad.accessmediaproductions.com^ ||ad.adriver.ru^$domain=firstrownow.eu|kyivpost.com|uatoday.tv|unian.info ||ad.aquamediadirect.com^$third-party ||ad.e-kolay.net^$third-party ||ad.flux.com^ ||ad.foxnetworks.com^ ||ad.ghfusion.com^$third-party ||ad.icasthq.com^ ||ad.idgtn.net^ ||ad.imad.co.kr^$third-party ||ad.indomp3z.us^$third-party ||ad.jamba.net^ ||ad.jokeroo.com^$third-party ||ad.lijit.com^$third-party ||ad.linkstorms.com^$third-party ||ad.livere.co.kr^ ||ad.mail.ru^ ||ad.mesomorphosis.com^ ||ad.mygamesol.com^$third-party ||ad.netcommunities.com^$third-party ||ad.outsidehub.com^ ||ad.pickple.net^ ||ad.premiumonlinemedia.com^$third-party ||ad.proxy.sh^ ||ad.r.worldssl.net^ ||ad.rambler.ru^ ||ad.realmcdn.net^$third-party ||ad.reklamport.com^ ||ad.sensismediasmart.com.au^ ||ad.sharethis.com^$third-party ||ad.smartclip.net^ ||ad.spielothek.so^ ||ad.sponsoreo.com^$third-party ||ad.valuecalling.com^$third-party ||ad.vidaroo.com^ ||ad.winningpartner.com^ ||ad.wsod.com^$third-party ||ad.zaman.com.tr^$third-party ||ad2links.com/js/$third-party ||adap.tv/redir/client/static/as3adplayer.swf ||adap.tv/redir/plugins/$object-subrequest ||adap.tv/redir/plugins3/$object-subrequest ||addme.com/images/addme_$third-party ||adf.ly/?$subdocument,~third-party,domain=adf.ly ||adf.ly/images/banners/ ||adf.ly/js/$third-party,domain=~j.gs|~q.gs ||adf.ly^*/link-converter.js$third-party ||adfoc.us/js/$third-party ||adingo.jp.eimg.jp^ ||adlandpro.com^$third-party ||adm.shinobi.jp^$third-party ||adn.ebay.com^ ||adplus.goo.mx^ ||adr-*.vindicosuite.com^ ||ads.dynamicyield.com^$third-party ||ads.mp.mydas.mobi^ ||adscaspion.appspot.com^ ||adserv.legitreviews.com^$third-party ||adsrv.eacdn.com^$third-party ||adss.dotdo.net^ ||adstest.zaman.com.tr^$third-party ||advanced-intelligence.com/banner ||adz.zwee.ly^ ||adziff.com^*/zdcse.min.js ||afcdn.com^*/ova-jw.swf$object-subrequest ||aff.cupidplc.com^$third-party ||aff.eteachergroup.com^ ||aff.marathonbet.com^ ||aff.svjump.com^ ||affil.mupromo.com^ ||affiliate.juno.co.uk^$third-party ||affiliate.mediatemple.net^$third-party ||affiliatehub.skybet.com^$third-party ||affiliateprogram.keywordspy.com^ ||affiliates-cdn.mozilla.org^$third-party ||affiliates.allposters.com^ ||affiliates.bookdepository.co.uk^$third-party ||affiliates.bookdepository.com^$third-party ||affiliates.homestead.com^$third-party ||affiliates.lynda.com^$third-party ||affiliates.picaboocorp.com^$third-party ||affiliatesmedia.sbobet.com^ ||affiliation.filestube.com^$third-party ||affiliation.fotovista.com^ ||affutdmedia.com^$third-party ||afimg.liveperson.com^$third-party ||agenda.complex.com^ ||agoda.net/banners/ ||ahlanlive.com/newsletters/banners/$third-party ||airvpn.org/images/promotional/ ||ais.abacast.com^ ||ak.imgaft.com^$third-party ||ak1.imgaft.com^$third-party ||akamai.net^*.247realmedia.com/$third-party ||akamai.net^*/espnpreroll/$object-subrequest ||akamai.net^*/pics.drugstore.com/prodimg/promo/ ||akamaihd.net/preroll*.mp4?$domain=csnnw.com ||akamaihd.net/ssa/*?zoneid=$subdocument ||akamaihd.net^*/web/pdk/swf/freewheel.swf?$third-party ||alexa.com^*/promotebuttons/ ||algart.net*_banner_$third-party ||allposters.com^*/banners/ ||allsend.com/public/assets/images/ ||alluremedia.com.au^*/campaigns/ ||alpsat.com/banner/ ||altushost.com/docs/$third-party ||amazon.com/?_encoding*&linkcode$third-party ||amazon.com/gp/redirect.html?$subdocument,third-party ||amazon.com^*/getaanad?$third-party ||amazonaws.com/ad_w_intersitial.html ||amazonaws.com/ansible.js$domain=motherjones.com ||amazonaws.com/banner/$domain=gserp.com ||amazonaws.com/bo-assets/production/banner_attachments/ ||amazonaws.com/btrb-prd-banners/ ||amazonaws.com/digitalcinemanec.swf$domain=boxoffice.com ||amazonaws.com/fvefwdds/ ||amazonaws.com/lms/sponsors/ ||amazonaws.com/newscloud-production/*/backgrounds/$domain=crescent-news.com|daily-jeff.com|recordpub.com|state-journal.com|the-daily-record.com|the-review.com|times-gazette.com ||amazonaws.com/photos.offers.analoganalytics.com/ ||amazonaws.com/pmb-musics/download_itunes.png ||amazonaws.com/publishflow/ ||amazonaws.com/skyscrpr.js ||amazonaws.com/streetpulse/ads/ ||amazonaws.com/widgets.youcompare.com.au/ ||amazonaws.com/youpop/ ||analytics.disneyinternational.com^ ||angelbc.com/clients/*/banners/$third-party ||anime.jlist.com^$third-party ||anonym.to/*findandtry.com ||any.gs/visitScript/$third-party ||aol.co.uk^*/cobrand.js ||aolcdn.com/os/mapquest/marketing/promos/ ||aolcdn.com/os/mapquest/promo-images/ ||aolcdn.com/os/music/img/*-skin.jpg ||api.140proof.com^$third-party ||api.bitp.it^$third-party ||api.groupon.com/v2/deals/$third-party ||api.ticketnetwork.com/Events/TopSelling/domain=nytimes.com ||apnonline.com.au/img/marketplace/*_ct50x50.gif ||appdevsecrets.com/images/nuts/ ||apple.com/itunesaffiliates/ ||appsgenius.com/images/$third-party ||appwork.org/hoster/banner_$third-party ||arcadetown.com/as/show.asp ||ard.ihookup.com^ ||arntrnassets.mediaspanonline.com^*_HP_wings_ ||artistdirect.com/partner/ ||as.devbridge.com^$third-party ||as.jivox.com/jivox/serverapis/getcampaignbysite.php?$object-subrequest ||assets.betterbills.com/widgets/ ||associmg.com^*.gif?tag- ||astalavista.box.sk/c-astalink2a.jpg ||astrology.com/partnerpages/ ||athena-ads.wikia.com^$third-party ||augine.com/widget|$third-party ||autoprivileges.net/news/ ||awadhtimes.com^$third-party ||award.sitekeuring.net^ ||axandra.com/affiliates/ ||axisbank.com/shopaholics-festival/$domain=ibnlive.in.com ||b.babylon.com^ ||b.livesport.eu^ ||b.sell.com^$third-party ||b117f8da23446a91387efea0e428392a.pl^$domain=ddlvalley.net ||b92.putniktravel.com^ ||b92s.net/images/banners/ ||babylon.com/site/images/common.js$third-party ||babylon.com/systems/af/landing/$third-party ||babylon.com/trans_box/*&affiliate= ||babylon.com^*?affid= ||badoo.com/informer/$third-party ||ball2win.com/Affiliate/ ||bamstudent.com/files/banners/ ||bankrate.com/jsfeeds/$third-party ||bankrate.com^$subdocument,domain=yahoo.com ||banman.isoftmarketing.com^$third-party ||banner.101xp.com^ ||banner.3ddownloads.com^ ||banner.europacasino.com^ ||banner.telefragged.com^ ||banner.titancasino.com^ ||banner.titanpoker.com^$third-party ||banner2.casino.com^$third-party ||bannermaken.nl/banners/$third-party ||banners.cfspm.com.au^$third-party ||banners.ixitools.com^$third-party ||banners.moreniche.com^$third-party ||banners.smarttweak.com^$third-party ||banners.videosz.com^$third-party ||banners.webmasterplan.com^$third-party ||bbcchannels.com/workspace/uploads/ ||bc.coupons.com^$third-party ||bc.vc/js/link-converter.js$third-party ||beachcamera.com/assets/banners/ ||bee4.biz/banners/ ||bemyapp.com/trk/$third-party ||bergen.com^*/sponsoredby- ||berush.com/images/*_semrush_$third-party ||berush.com/images/semrush_banner_ ||berush.com/images/whorush_120x120_ ||besthosting.ua/banner/ ||bestofmedia.com/ws/communicationSpot.php? ||bet-at-home.com/oddbanner.aspx? ||beta.down2crazy.com^$third-party ||betterbills.com.au/widgets/ ||betting.betfair.com^$third-party ||betwaypartners.com/affiliate_media/$third-party ||bharatmatrimony.com/matrimoney/matrimoneybanners/$third-party ||bidgo.ca^$subdocument,third-party ||bidorbuy.co.za/jsp/system/referral.jsp? ||bidorbuy.co.za/jsp/tradesearch/TradeFeedPreview.jsp?$third-party ||bigcommerce.com^*/product_images/$domain=politicalears.com ||bigpond.com/specials/$subdocument,third-party ||bigrock.in/affiliate/ ||bijk.com^*/banners/ ||binbox.io/public/img/promo/$third-party ||binopt.net/banners/ ||bit.ly^$subdocument,domain=adf.ly ||bitcoindice.com/img/bitcoindice_$third-party ||bitcoinwebhosting.net/banners/$third-party ||bitshare.com^*/banner/ ||bittorrent.am/serws.php?$third-party ||bl.wavecdn.de^ ||blamads-assets.s3.amazonaws.com^ ||blindferret.com/images/*_skin_ ||blinkx.com/?i=*&adc_pub_id=$script,third-party ||blinkx.com/f2/overlays/ ||bliss-systems-api.co.uk^$third-party ||blissful-sin.com/affiliates/ ||blocks.ginotrack.com^$third-party ||bloodstock.uk.com/affiliates/ ||bluepromocode.com/images/widgets/$third-party ||bluesattv.net/bluesat.swf ||bluhostedbanners.blucigs.com^ ||bo-videos.s3.amazonaws.com^$third-party ||boago.com^*_Takeover_ ||bollyrulez.net/media/adz/ ||booking.com/general.html?$domain=timeout.com ||booking.com^*;tmpl=banner_ ||bookingdragon.com^$subdocument,third-party ||bordernode.com/images/$third-party ||borrowlenses.com/affiliate/ ||bosh.tv/hdplugin. ||box.anchorfree.net^ ||bpath.com/affiliates/ ||bplaced.net/pub/ ||bravenet.com/cserv.php ||break.com/break/html/$subdocument ||break.com^*/partnerpublish/ ||brettterpstra.com/wp-content/uploads/$third-party ||broadbandgenie.co.uk/widget?$third-party ||bruteforceseo.com/affiliates/ ||bruteforcesocialmedia.com/affiliates/ ||bsrv.adohana.com^$third-party ||btguard.com/images/$third-party ||btr.domywife.com^ ||btrd.net/assets/interstitial$script ||bubbles-uk.com/banner/$third-party ||bullguard.com^*/banners/ ||burst.net/aff/ ||burstnet.akadns.net^$image ||businessnewswatch.ca/images/nnwbanner/ ||buy.com^*/affiliate/ ||buzznet.com^*/showpping-banner-$third-party ||byzoo.org/script/tu*.js ||cal-one.net/ellington/deals_widget.php? ||cal-one.net/ellington/search_form.php? ||camelmedia.net^*/banners/ ||cancomdigital.com/resourcecenter/$third-party ||canonresourcecenter.com^$third-party ||carbiz.in/affiliates-and-partners/ ||careerjunction.co.za/widgets/$third-party ||careerjunction.co.za^*/widget?$third-party ||carfax.com/img_myap/$third-party ||cars.fyidriving.com^$subdocument,third-party ||cas.clickability.com^ ||cash.neweramediaworks.com^ ||cashmakingpowersites.com^*/banners/ ||cashmyvideo.com/images/cashmyvideo_banner.gif ||casinobonusdeal.com^$subdocument,domain=frombar.com|gledaisport.com|smotrisport.com|sportcategory.com|sportlemon.org|sportlemon.tv ||castasap.com/publi2.html ||casti.tv/adds/ ||catholicweb.com^*/banners/ ||cbpirate.com/getimg.php? ||cccam.co/banner_big.gif ||cdn.assets.gorillanation.com^$third-party ||cdn.cdncomputer.com/js/main.js ||cdn.ndparking.com/js/init.min.js ||cdn.offcloud.com^$third-party ||cdn.pubexchange.com/modules/display/$script ||cdn.sweeva.com/images/$third-party ||cdnpark.com/scripts/js3.js ||cdnprk.com/scripts/js3.js ||cdnprk.com/scripts/js3caf.js ||centralmediaserver.com^*_side_bars.jpg ||centralscotlandjoinery.co.uk/images/csj-125.gif$third-party ||cerebral.typn.com^ ||cex.io/img/b/ ||cex.io/informer/$third-party ||cfcdn.com/showcase_sample/search_widget/ ||cgmlab.com/tools/geotarget/custombanner.js ||chacsystems.com/gk_add.html$third-party ||challies.com^*/wtsbooks5.png$third-party ||charlestondealstoday.com/aux/ux/_component/ss_dealrail/$subdocument,third-party ||choices.truste.com^$third-party ||chriscasconi.com/nostalgia_ad. ||cimg.in/images/banners/ ||circularhub.com^*/circularhub_module.js$third-party ||citygridmedia.com/ads/ ||cjmooter.xcache.kinxcdn.com^ ||clarity.abacast.com^ ||click.eyk.net^ ||clickstrip.6wav.es^ ||clicksure.com/img/resources/banner_ ||clipdealer.com/?action=widget&*&partner= ||cloudfront.net/nimblebuy/ ||cloudfront.net/scripts/js3caf.js ||cloudzer.net/ref/ ||cloudzer.net^*/banner/$third-party ||cngroup.co.uk/service/creative/ ||cnhionline.com^*/rtj_ad.jpg ||cnnewmedia.co.uk/locker/ ||code.popup2m.com^$third-party ||colmwynne.com^$image,third-party ||colorlabsproject.com^*/banner_ ||complexmedianetwork.com/cdn/agenda.complex.com/$domain=~complex.com ||comx-computers.co.za/banners/$third-party ||conduit.com//banners/$third-party ||connect.summit.co.uk^ ||connectok.com/brightcove/?$domain=newsok.com ||consolpub.com/weatherwindow/ ||content.livesportmedia.eu^ ||content.secondspace.com^$~image,third-party ||contentcastsyndication.com^*&banner ||continent8.com^*/bannerflow/ ||conversionplanet.com/published/feeds/$third-party ||couponcp-a.akamaihd.net^$third-party ||couptopia.com/affiliate/$third-party ||coxnewsweb.com^*/ads/ ||cplayer.blinkx.com^$third-party ||cpm.amateurcommunity.de^ ||creatives.inmotionhosting.com^ ||creatives.summitconnect.co.uk^ ||crowdsavings.com/r/banner/ ||cruisesalefinder.co.nz/affiliates.html$third-party ||crunchyroll.com/awidget/$third-party ||cstv.com^*/sponsors/ ||cts.tradepub.com/cts4/?ptnr=*&tm=$third-party ||cursecdn.com/banner/ ||cursecdn.com/shared-assets/current/anchor.js?id=$third-party ||customcodebydan.com/images/banner.gif ||customer.heartinternet.co.uk^$third-party ||cuteonly.com/banners.php$third-party ||d-l-t.com^$subdocument,third-party ||d13czkep7ax7nj.cloudfront.net^ ||d15565yqt7pv7r.cloudfront.net^ ||d15gt9gwxw5wu0.cloudfront.net^ ||d17f2fxw547952.cloudfront.net^ ||d19972r8wdpby8.cloudfront.net^ ||d1ade4ciw4bqyc.cloudfront.net^ ||d1cl1sqtf3o420.cloudfront.net^ ||d1d95giojjkirt.cloudfront.net^ ||d1ep3cn6qx0l3z.cloudfront.net^ ||d1ey3fksimezm4.cloudfront.net^ ||d1fo96xm8fci0r.cloudfront.net^ ||d1gojtoka5qi10.cloudfront.net^ ||d1k74lgicilrr3.cloudfront.net^ ||d1noellhv8fksc.cloudfront.net^ ||d1pcttwib15k25.cloudfront.net^ ||d1pdpbxj733bb1.cloudfront.net^ ||d1spb7fplenrp4.cloudfront.net^ ||d1vbm0eveofcle.cloudfront.net^ ||d1zgderxoe1a.cloudfront.net^ ||d23guct4biwna6.cloudfront.net^ ||d23nyyb6dc29z6.cloudfront.net^ ||d25ruj6ht8bs1.cloudfront.net^ ||d26dzd2k67we08.cloudfront.net^ ||d26j9bp9bq4uhd.cloudfront.net^ ||d26wy0pxd3qqpv.cloudfront.net^ ||d27jt7xr4fq3e8.cloudfront.net^ ||d287x05ve9a63s.cloudfront.net^ ||d29r6igjpnoykg.cloudfront.net^ ||d2anfhdgjxf8s1.cloudfront.net^ ||d2b2x1ywompm1b.cloudfront.net^ ||d2b65ihpmocv7w.cloudfront.net^ ||d2bgg7rjywcwsy.cloudfront.net^ ||d2cxkkxhecdzsq.cloudfront.net^ ||d2d2lbvq8xirbs.cloudfront.net^ ||d2dxgm96wvaa5j.cloudfront.net^ ||d2gpgaupalra1d.cloudfront.net^ ||d2gtlljtkeiyzd.cloudfront.net^ ||d2gz6iop9uxobu.cloudfront.net^ ||d2hap2bsh1k9lw.cloudfront.net^ ||d2ipklohrie3lo.cloudfront.net^ ||d2mic0r0bo3i6z.cloudfront.net^ ||d2mq0uzafv8ytp.cloudfront.net^ ||d2nlytvx51ywh9.cloudfront.net^ ||d2o307dm5mqftz.cloudfront.net^ ||d2oallm7wrqvmi.cloudfront.net^ ||d2omcicc3a4zlg.cloudfront.net^ ||d2pgy8h4i30on1.cloudfront.net^ ||d2plxos94peuwp.cloudfront.net^ ||d2r359adnh3sfn.cloudfront.net^ ||d2tgev5wuprbqq.cloudfront.net^ ||d2tnimpzlb191i.cloudfront.net^ ||d2ubicnllnnszy.cloudfront.net^ ||d2v4glj2m8yzg5.cloudfront.net^ ||d2v9ajh2eysdau.cloudfront.net^ ||d2vt6q0n0iy66w.cloudfront.net^ ||d2yhukq7vldf1u.cloudfront.net^ ||d2z1smm3i01tnr.cloudfront.net^ ||d31807xkria1x4.cloudfront.net^ ||d32pxqbknuxsuy.cloudfront.net^ ||d33f10u0pfpplc.cloudfront.net^ ||d33otidwg56k90.cloudfront.net^ ||d34obr29voew8l.cloudfront.net^ ||d37kzqe5knnh6t.cloudfront.net^ ||d38pxm3dmrdu6d.cloudfront.net^ ||d38r21vtgndgb1.cloudfront.net^ ||d39xqloz8t5a6x.cloudfront.net^ ||d3bvcf24wln03d.cloudfront.net^ ||d3dphmosjk9rot.cloudfront.net^ ||d3f9mcik999dte.cloudfront.net^ ||d3fzrm6pcer44x.cloudfront.net^ ||d3irruagotonpp.cloudfront.net^ ||d3iwjrnl4m67rd.cloudfront.net^ ||d3lvr7yuk4uaui.cloudfront.net^ ||d3lzezfa753mqu.cloudfront.net^ ||d3m41swuqq4sv5.cloudfront.net^ ||d3nvrqlo8rj1kw.cloudfront.net^ ||d3p9ql8flgemg7.cloudfront.net^ ||d3pkae9owd2lcf.cloudfront.net^ ||d3q2dpprdsteo.cloudfront.net^ ||d3qszud4qdthr8.cloudfront.net^ ||d3t2wca0ou3lqz.cloudfront.net^ ||d3t9ip55bsuxrf.cloudfront.net^ ||d3tdefw8pwfkbk.cloudfront.net^ ||d3vc1nm9xbncz5.cloudfront.net^ ||d5pvnbpawsaav.cloudfront.net^ ||d6bdy3eto8fyu.cloudfront.net^ ||d8qy7md4cj3gz.cloudfront.net^ ||dailydealstwincities.com/widgets/$subdocument,third-party ||dal9hkyfi0m0n.cloudfront.net^ ||dapatwang.com/images/banner/ ||dart.clearchannel.com^ ||dasfdasfasdf.no-ip.info^ ||data.neuroxmedia.com^ ||datafeedfile.com/widget/readywidget/ ||datakl.com/banner/ ||daterly.com/*.widget.php$third-party ||dawanda.com/widget/$third-party ||dbam.dashbida.com^ ||ddwht76d9jvfl.cloudfront.net^ ||dealextreme.com/affiliate_upload/$third-party ||dealplatform.com^*/widgets/$third-party ||deals.buxr.net^$third-party ||deals.macupdate.com^$third-party ||deals4thecure.com/widgets/*?affiliateurl= ||dealswarm.com^$subdocument,third-party ||dealtoday.com.mt/banners/ ||dealzone.co.za^$script,third-party ||delivery.importantmedia.org^$third-party ||dennis.co.uk^*/siteskins/ ||depositfiles.com^*.php?ref= ||desi4m.com/desi4m.gif$third-party ||deskbabes.com/ref.php? ||desperateseller.co.uk/affiliates/ ||detroitmedia.com/jfry/ ||dev-cms.com^*/promobanners/ ||developermedia.com/a.min.js ||dew9ckzjyt2gn.cloudfront.net^ ||dhgate.com^$third-party,domain=sammyhub.com ||digitalmediacommunications.com/belleville/employment/ ||digitalsatellite.tv/banners/ ||direct.quasir.info^$third-party ||directnicparking.com^$third-party ||display.digitalriver.com^ ||disqus.com/listPromoted? ||disy2s34euyqm.cloudfront.net^ ||dizixdllzznrf.cloudfront.net^ ||djlf5xdlz7m8m.cloudfront.net^ ||dkd69bwkvrht1.cloudfront.net^ ||dkdwv3lcby5zi.cloudfront.net^ ||dl392qndlveq0.cloudfront.net^ ||dl5v5atodo7gn.cloudfront.net^ ||dlupv9uqtjlie.cloudfront.net^ ||dm0acvguygm9h.cloudfront.net^ ||dm8srf206hien.cloudfront.net^ ||dntrck.com/trax? ||domainapps.com/assets/img/domain-apps.gif$third-party ||domaingateway.com/js/redirect-min.js ||domainnamesales.com/return_js.php? ||dorabet.com/banner/ ||dot.tk/urlfwd/searchbar/bar.html ||dotz123.com/run.php? ||download-provider.org/?aff.id=$third-party ||download.bitdefender.com/resources/media/$third-party ||downloadandsave-a.akamaihd.net^$third-party ||downloadprovider.me/en/search/*?aff.id=*&iframe=$third-party ||dp51h10v6ggpa.cloudfront.net^ ||dpsq2uzakdgqz.cloudfront.net^ ||dq2tgxnc2knif.cloudfront.net^ ||dramafever.com/widget/$third-party ||dramafeverw2.appspot.com/widget/$third-party ||dreamboxcart.com/earning/$third-party ||dreamhost.com/rewards/$third-party ||dreamstime.com/banner/ ||dreamstime.com/img/badges/banner$third-party ||dreamstime.com/refbanner- ||droidnetwork.net/img/dt-atv160.jpg ||droidnetwork.net/img/vendors/ ||dropbox.com^*/aff-resources/$domain=gramfeed.com ||dttek.com/sponsors/ ||dvdfab.com/images/fabnewbanner/$third-party ||dvf2u7vwmkr5w.cloudfront.net^ ||dx.com/affiliate/$third-party ||dx5qvhwg92mjd.cloudfront.net^ ||dxq6c0tx3v6mm.cloudfront.net^ ||dxqd86uz345mg.cloudfront.net^ ||dycpc40hvg4ki.cloudfront.net^ ||dyl3p6so5yozo.cloudfront.net^ ||dynamicserving.com^$third-party ||dynw.com/banner ||e-tailwebstores.com/accounts/default1/banners/ ||e-webcorp.com/images/$third-party ||easy-share.com/images/es20/ ||easyretiredmillionaire.com/img/aff-img/ ||eattoday.com.mt/widgets/$third-party ||ebaycommercenetwork.com/publisher/$third-party ||ebaystatic.com/aw/signin/ebay-signin-toyota- ||ebladestore.com^*/banners/ ||eblastengine.upickem.net^$third-party ||echineselearning.com^*/banner.jpg ||ectaco-store.com^*/promo.jsp? ||edge.viagogo.co.uk^*/widget.ashx?$third-party ||edgecastcdn.net^*.barstoolsports.com/wp-content/banners/ ||eholidayfinder.com/images/logo.gif$third-party ||elenasmodels.com/cache/cb_$third-party ||elitsearch.com^$subdocument,third-party ||elliottwave.com/fw/regular_leaderboard.js ||eltexonline.com/contentrotator/$third-party ||emailcashpro.com/images/$third-party ||emsisoft.com/bnr/ ||engine.gamerati.net^$third-party ||enticelabs.com/el/ ||eplreplays.com/wl/ ||epowernetworktrackerimages.s3.amazonaws.com^ ||escape.insites.eu^$third-party ||esport-betting.com^*/betbanner/ ||etoolkit.com/banner/$third-party ||etoro.com/B*_A*_TGet.aspx$third-party ||etrader.kalahari.com^$third-party ||etrader.kalahari.net^$third-party ||europolitique.info^*/pub/ ||euwidget.imshopping.com^ ||events.kalooga.com^ ||everestpoker.com^*/?adv= ||exoplanetwar.com/l/landing.php? ||expekt.com/affiliates/ ||explorer.sheknows.com^$third-party ||ext.theglobalweb.com^ ||extabit.com/s/$third-party ||extensoft.com/artisteer/banners/ ||extras.mercurynews.com/tapin_directory/ ||extras.mnginteractive.com^*/todaysdeals.gif ||exwp.org/partners/ ||eyetopics.com/content_images/$third-party ||fairfaxregional.com.au/proxy/commercial-partner-solar/ ||familytreedna.com/img/affiliates/ ||fancybar.net/ac/fancybar.js?zoneid$third-party ||fantasyplayers.com/templates/banner_code. ||fantaz.com^*/banners/$third-party ||fapturbo.com/testoid/ ||farmholidays.is/iframeallfarmsearch.aspx?$third-party ||fastcccam.com/images/fcbanner2.gif ||fatads.toldya.com^$third-party ||fatburningfurnace.com^*/fbf-banner- ||fcgadgets.blogspot.com^$third-party ||feedburner.com/~a/ ||feeds.logicbuy.com^ ||fenixm.com/actions/*Skin*.$image ||filedownloader.net/design/$third-party ||filedroid.net/af_ta/$third-party ||filefactory.com^*/refer.php?hash= ||filejungle.com/images/banner/ ||fileloadr.com^$third-party ||fileparadox.com/images/banner/ ||filepost.com/static/images/bn/ ||fileserve.com/images/banner_$third-party ||fileserver1.net/download ||filmehd.net/imagini/banner_$third-party ||filmreel.tv^$domain=thepiratebay.si ||filterforge.com/images/banners/ ||fimserve.myspace.com^$third-party ||firecenter.pl/banners/ ||firstclass-download.com^$subdocument,third-party ||flagship.asp-host.co.uk^$third-party ||flipchat.com/index.php?$third-party ||flipkart.com/affiliate/displayWidget?$third-party ||flipkart.com/affiliateWidget/$third-party ||flower.com/img/lsh/ ||followfairy.com/followfairy300x250.jpg ||footymad.net/partners/ ||forms.aweber.com/form/styled_popovers_and_lightboxes.js$third-party ||fortune5minutes.com^*/banner_ ||forumimg.ipmart.com/swf/img.php ||fragfestservers.com/bannerb.gif ||freakshare.com/?ref= ||freakshare.com/banner/$third-party ||freakshare.net/banner/ ||free-football.tv/images/usd/ ||freecycle.org^*/sponsors/ ||freetrafficsystem.com/fts/ban/ ||freetricktipss.info^$subdocument,third-party ||freewheel.mtgx.tv^$~object-subrequest ||freshbooks.com/images/banners/$third-party ||friedrice.la/widget/$third-party ||frogatto.com/images/$third-party ||frontsight.com^*/banners/ ||ft.pnop.com^ ||fugger.ipage.com^$third-party ||fugger.netfirms.com/moa.swf$third-party ||funtonia.com/promo/ ||fupa.com/aw.aspx?$third-party ||furiousteam.com^*/external_banner/ ||futuboxhd.com/js/bc.js ||futuresite.register.com/us?$third-party ||fxcc.com/promo/ ||fxultima.com/banner/ ||fyicentralmi.com/remote_widget?$third-party ||fyiwashtenaw.com/remote_widget? ||fyygame.com/images/*.swf$third-party ||gadgetresearch.net^$subdocument,third-party ||gamblingwages.com/images/$third-party ||gameduell.com/res/affiliate/ ||gameorc.net/a.html ||gamersaloon.com/images/banners/ ||gamesports.net/img/betting_campaigns/ ||gamestop.com^*/aflbanners/ ||gamingjobsonline.com/images/banner/ ||gateway.fortunelounge.com^ ||gateways.s3.amazonaws.com^ ||gawkerassets.com/assets/marquee/$object,third-party ||ge.tt/api/$domain=mhktricks.net ||generic4all.com^*?refid=$third-party ||geo.connexionsecure.com^ ||geobanner.friendfinder.com^ ||geobanner.passion.com^ ||get.2leep.com^$third-party ||get.box24casino.com^$third-party ||get.davincisgold.com^$third-party ||get.paradise8.com^$third-party ||get.rubyroyal.com^$third-party ||get.slotocash.com^$third-party ||get.thisisvegas.com^$third-party ||getadblock.com/images/adblock_banners/$third-party ||gethopper.com/tp/$third-party ||getnzb.com/img/partner/banners/$third-party ||getpaidforyourtime.org/basic-rotating-banner/ ||gfaf-banners.s3.amazonaws.com^ ||gfxa.sheetmusicplus.com^$third-party ||ggmania.com^*.jpg$third-party ||giantrealm.com/saj/ ||giantsavings-a.akamaihd.net^$third-party ||giffgaff.com/banner/ ||glam.com/gad/ ||glam.com^*?affiliateid= ||globalprocash.com/banner125.gif ||gmstatic.net^*/amazonbadge.png ||gmstatic.net^*/itunesbadge.png ||go2cloud.org/aff_i? ||goadv.com^*/ads.js ||gogousenet.com^*/promo.cgi ||gogousenet.com^*/promo2.cgi ||gold4rs.com/images/$third-party ||goldmoney.com/~/media/Images/Banners/$third-party ||google.com/pagead/ ||google.com/uds/afs?*adsense$subdocument ||googlesyndication.com/pagead/$third-party ||googlesyndication.com/safeframe/$third-party ||googlesyndication.com/simgad/$third-party ||googlesyndication.com^*/click_to_buy/$object-subrequest,third-party ||googlesyndication.com^*/domainpark.cgi? ||googlesyndication.com^*/googlevideoadslibraryas3.swf$object-subrequest,third-party ||gorgonprojectinvest.com/images/banners/ ||gotraffic.net^*/sponsors/ ||govids.net/adss/ ||graboid.com/affiliates/ ||graduateinjapan.com/affiliates/ ||grammar.coursekey.com/inter/$third-party ||groupon.com/javascripts/common/affiliate_widget/$third-party ||grouponcdn.com^*/affiliate_widget/$third-party ||gsniper.com/images/$third-party ||guim.co.uk/guardian/thirdparty/tv-site/side.html ||guzzle.co.za/media/banners/ ||halllakeland.com/banner/ ||handango.com/marketing/affiliate/ ||haymarket-whistleout.s3.amazonaws.com/*_ad.html ||haymarket.net.au/Skins/ ||hdvid-codecs.com^$third-party ||heidiklein.com/media/banners/ ||hexero.com/images/banner.gif ||hide-my-ip.com/promo/ ||highepcoffer.com/images/banners/ ||hitleap.com/assets/banner- ||hitleap.com/assets/banner.png ||hm-sat.de/b.php ||hostdime.com/images/affiliate/$third-party ||hostgator.com/~affiliat/cgi-bin/affiliates/$third-party ||hosting.conduit.com^$third-party ||hostinger.nl/banners/ ||hostmonster.com/src/js/izahariev/$third-party ||hotelsbycity.com^*/bannermtg.php?$third-party ||hoteltravel.com/partner/$third-party ||hotlinking.dosmil.imap.cc^$third-party ||hqfootyad4.blogspot.com^$third-party ||hstpnetwork.com/ads/ ||hstpnetwork.com/zeus.php ||hubbarddeals.com^*/promo/ ||hubbardradio.com^*/my_deals.php ||hyipregulate.com/images/hyipregulatebanner.gif ||hyperfbtraffic.com/images/graphicsbanners/ ||hyperscale.com/images/adh_button.jpg ||i.lsimg.net^*/sides_clickable. ||i.lsimg.net^*/takeover/ ||ibsrv.net/sidetiles/125x125/ ||ibsrv.net/sponsor_images/ ||ibsys.com/sh/sponsors/ ||ibvpn.com/img/banners/ ||icastcenter.com^*/amazon-buyfrom.gif ||icastcenter.com^*/itunes.jpg ||idealo.co.uk/priceinfo/$third-party ||idg.com.au/ggg/images/*_home.jpg$third-party ||idup.in/embed$third-party,domain=ganool.com ||ifilm.com/website/*_skin_$third-party ||ilapi.ebay.com^$third-party ||im.ov.yahoo.co.jp^ ||ima3vpaid.appspot.com^ ||image.com.com^*/skin2.jpg$third-party ||image.dhgate.com^*/dhgate-logo-$third-party ||images-amazon.com/images/*/associates/widgets/ ||images-amazon.com/images/*/banner/$third-party ||images-amazon.com^$domain=cloudfront.net ||images-pw.secureserver.net/images/100yearsofchevy.gif ||images-pw.secureserver.net^*_*.$image,third-party ||images.dreamhost.com^$third-party ||images.mylot.com^$third-party ||images.youbuy.it/images/$third-party ||imagetwist.com/banner/ ||img.bluehost.com^$third-party ||img.hostmonster.com^$third-party ||img.mybet.com^$third-party ||img.promoddl.com^$third-party ||img.servint.net^$third-party ||imgdino.com/gsmpop.js ||imgehost.com^*/banners/$third-party ||imgur.com^$image,domain=talksport.com ||imptestrm.com/rg-main.php? ||indeed.fr/ads/ ||indian-forex.com^*/banners/$third-party ||indieclick.3janecdn.com^ ||infibeam.com/affiliate/$third-party ||infochoice.com.au/Handler/WidgetV2Handler.ashx? ||infomarine.gr/images/banerr.gif ||infomarine.gr^*/images/banners/ ||inisrael-travel.com/jpost/ ||init.lingospot.com^$third-party ||inline.playbryte.com^$third-party ||inskin.vo.llnwd.net^ ||instantpaysites.com/banner/ ||instaprofitgram.com/images/banners/ ||integrityvpn.com/img/integrityvpn.jpg ||intermrkts.vo.llnwd.net^$third-party ||internetbrands.com/partners/$third-party ||interserver.net/logos/vps-$third-party ||interstitial.glsp.netdna-cdn.com^$third-party ||intexchange.ru/Content/banners/ ||iobit.com/partner/$third-party ||ipercast.net^*/ova-jw.swf$object-subrequest ||ipixs.com/ban/$third-party ||iselectmedia.com^*/banners/ ||iwebzoo.com/banner/ ||iypcdn.com^*/bgbanners/ ||iypcdn.com^*/otherbanners/ ||iypcdn.com^*/ypbanners/ ||jalbum.net/widgetapi/js/dlbutton.js? ||jenningsforddirect.co.uk/sitewide/extras/$third-party ||jeysearch.com^$subdocument,third-party ||jimdo.com/s/img/aff/ ||jinx.com/content/banner/$third-party ||jivox.com/jivox/serverapis/getcampaignbyid.php?$object-subrequest ||joblet.jp/javascripts/$third-party ||jobs-affiliates.ws/images/$third-party ||jocly.com^*.html?click=$subdocument,third-party ||jrcdev.net/promos/ ||jsfeedget.com^$script,third-party ||jsrdn.com/s/1.js ||jubimax.com/banner_images/ ||jugglu.com/content/widgets/$third-party ||justclicktowatch.to/jstp.js ||jvzoo.com/assets/widget/$third-party ||k-po.com/img/ebay.png$third-party ||kaango.com/fecustomwidgetdisplay? ||kallout.com^*.php?id= ||kaltura.com^*/vastPlugin.swf$third-party ||keep2share.cc/images/i/00468x0060- ||keyword-winner.com/demo/images/ ||king.com^*/banners/ ||knorex.asia/static-firefly/ ||kontera.com/javascript/lib/KonaLibInline.js$third-party ||kozmetikcerrahi.com/banner/ ||kraken.giantrealm.com^$third-party ||krillion.com^*/productoffers.js ||kurtgeiger.com^*/linkshare/ ||l.yimg.com^*&partner=*&url= ||ladbrokes.com^*&aff_id= ||lapi.ebay.com^$third-party ||lastlocation.com/images/banner ||leadintelligence.co.uk/in-text.js$third-party ||leadsleap.com/images/banner_ ||leadsleap.com/widget/ ||legaljobscentre.com/feed/jobad.aspx ||legitonlinejobs.com/images/$third-party ||lego.com^*/affiliate/ ||lesmeilleurs-jeux.net/images/ban/$third-party ||lessemf.com/images/banner-$third-party ||letmewatchthis.ru/movies/linkbottom ||letters.coursekey.com/lettertemplates_$third-party ||lg.com/in/cinema3d.jsp$subdocument,third-party ||lifestyle24h.com/reward/$third-party ||lijit.com/adif_px.php ||lijit.com/delivery/ ||link.link.ru^$third-party ||linkbird.com/static/upload/*/banner/$third-party ||linkedin.com/csp/dtag?$subdocument,third-party ||lionheartdms.com^*/walmart_300.jpg ||litecoinkamikaze.com/assets/images/banner$third-party ||literatureandlatte.com/gfx/buynowaffiliate.jpg ||liutilities.com/partners/$third-party ||liutilities.com^*/affiliate/ ||livecrics.livet20worldcup.com/video.php$domain=iplstream.com ||liveperson.com/affiliates/ ||liveshows.com^*/live.js$third-party ||llnwd.net/o28/assets/*-sponsored- ||localdata.eu/images/banners/ ||london24.com^*/mpu/ ||longtailvideo.com*/ltas.swf ||longtailvideo.com^*/adaptvjw5-$object-subrequest ||longtailvideo.com^*/adaptvjw5.swf$object-subrequest ||longtailvideo.com^*/adawe-$object-subrequest,third-party ||longtailvideo.com^*/googima-$object-subrequest ||longtailvideo.com^*/googima.swf$object-subrequest,third-party ||longtailvideo.com^*/ltas-$object-subrequest,third-party ||longtailvideo.com^*/ova-$object-subrequest ||longtailvideo.com^*/yume-h.swf ||longtailvideo.com^*/yume.swf ||loopnet.com^*/searchwidget.htm$third-party ||loot.co.za/shop/product.jsp?$third-party ||lottoelite.com/banners/$third-party ||lowbird.com/random/$third-party ||lowcountrymarketplace.com/widgets/$third-party ||lp.longtailvideo.com^*/adaptv*.swf ||lp.ncdownloader.com^$third-party ||ltfm.ca/stats.php? ||lucky-ace-casino.net/banners/ ||lucky-dating.net/banners/ ||luckygunner.com^*/banners/ ||luckyshare.net/images/banners/ ||lumfile.com/lumimage/ourbanner/$third-party ||lygo.com/d/toolbar/sponsors/ ||lylebarn.com/crashwidget/$domain=crash.net ||lynku.com/partners/$third-party ||m.uploadedit.com^$third-party,domain=flysat.com ||maases.com/i/br/$domain=promodj.com ||madisonlogic.com^$third-party ||mads.aol.com^ ||magicaffiliateplugin.com/img/mga-125x125.gif ||magicmembers.com/img/mgm-125x125 ||magniwork.com/banner/ ||mahndi.com/images/banner/ ||mantra.com.au^*/campaigns/$third-party ||marinejobs.gr/images/marine_adv.gif ||marketing.888.com^ ||mastiway.com/webimages/$third-party ||match.com^*/prm/$third-party ||matchbin.com/javascripts/remote_widget.js ||matrixmails.com/images/$third-party ||maximainvest.net^$image,third-party ||mazda.com.au/banners/ ||mb-hostservice.de/banner_ ||mb.marathonbet.com^$third-party ||mb.zam.com^ ||mcc.godaddy.com/park/$subdocument,third-party ||mcclatchyinteractive.com/creative/ ||mdpcdn.com^*/gpt/ ||media-toolbar.com^$third-party ||media.enimgs.net/brand/files/escalatenetwork/ ||media.myspace.com/play/*/featured-videos-$third-party ||media.onlineteachers.co.in^$third-party ||mediaon.com/moneymoney/ ||mediaserver.digitec.ch^$subdocument,third-party ||mediaspanonline.com^*-Takeover- ||mediaspanonline.com^*-Takeover_ ||megalivestream.net/pub.js ||memepix.com/spark.php? ||meraad2.blogspot.com^$third-party ||metaboli.fr^*/adgude_$third-party ||metroland.com/wagjag/ ||mfcdn.net/store/spotlight/ ||mfeed.newzfind.com^$third-party ||mgprofit.com/images/*x$third-party ||microsoft.com^*/bannerrotator/$third-party ||microsoft.com^*/community/images/windowsintune/$third-party ||mightyape.co.nz/stuff/$third-party ||mightydeals.com/widget?$third-party ||mightydeals.com/widgets/$third-party ||mightydeals.s3.amazonaws.com/md_adv/ ||milanomoda.info^$domain=uploadlw.com ||millionaires-club-international.com/banner/ ||missnowmrs.com/images/banners/ ||mkini.net/banners/ ||mlive.com/js/oas/ ||mmdcash.com/mmdcash01.gif ||mmo4rpg.com^*.gif|$third-party ||mmosale.com/baner_images/$third-party ||mmwebhandler.888.com^$third-party ||mnginteractive.com^*/dartinclude.js ||mobilemetrics.appspot.com^$third-party ||mobyler.com/img/banner/ ||mol.im/i/pix/ebay/ ||moneycontrol.co.in^*PopUnder.js ||moneycontrol.com/share-market-game/$third-party ||moneywise.co.uk/affiliate/ ||moosify.com/widgets/explorer/?partner= ||mosso.com^*/banners/ ||mozo-widgets.f2.com.au^ ||mp3ix.com^$third-party ||mrc.org/sites/default/files/uploads/images/Collusion_Banner ||mrc.org^*/Collusion_Banner300x250.jpg ||mrc.org^*/take-over-charlotte300x250.gif ||msecnd.net/scripts/*.pop.$script ||msm.mysavings.com^*.asp?afid=$third-party ||msnbcmedia.msn.com^*/sponsors/ ||mt.sellingrealestatemalta.com^$third-party ||mto.mediatakeout.com^$third-party ||multisitelive.com^*/banner_ ||multivizyon.tv^*/flysatbanner.swf ||musicmemorization.com/images/$third-party ||musik-a-z.com^$subdocument,third-party ||my-best-jobs.com^$subdocument,third-party ||my-dirty-hobby.com/track/$subdocument,third-party ||myalter1tv.altervista.org^$subdocument,third-party ||mydirtyhobby.com^$third-party,domain=~my-dirty-hobby.com|~mydirtyhobby.de ||mydownloader.net/banners/$third-party ||myfreepaysite.info^*.gif$third-party ||myfreeresources.com/getimg.php?$third-party ||myfreeshares.com/120x60b.gif ||myhpf.co.uk/banners/ ||mylife.com/partner/$third-party ||myspace.com/play/myspace/*&locationId$third-party ||mytrafficstrategy.com/images/$third-party ||myusenet.net/promo.cgi? ||myvi.ru/feed/$object-subrequest ||mzstatic.com^$image,object-subrequest,domain=dailymotion.com ||n.nu/banner.js ||namecheap.com/graphics/linkus/$third-party ||nanobrokers.com/img/banner_ ||nanoinvestgroup.com/images/banner*.gif ||neogames-tech.com/resources/genericbanners/ ||nesgamezone.com/syndicate? ||netdigix.com/google_banners/ ||netdna-cdn.com/wp-content/plugins/background-manager/$domain=7daysindubai.com ||netdna-cdn.com^*-300x250.$domain=readersdigest.co.uk ||netdna-cdn.com^*-Background-1280x10241.$domain=7daysindubai.com ||nettvplus.com/images/banner_ ||network.aufeminin.com^ ||network.business.com^ ||networkice.com^$subdocument,third-party ||news-whistleout.s3.amazonaws.com^$third-party ||newware.net/home/banner$third-party ||newware.net/home/newware-sm.png$third-party ||nimblecommerce.com/widget.action? ||nitropdf.com/graphics/promo/$third-party ||nlsl.about.com/img?$third-party ||nocookie.net^*/wikiasearchads.js ||novadune.com^$third-party ||nster.com/tpl/this/js/popnster.js ||nude.mk/images/$third-party ||numb.hotshare.biz^$third-party ||nwadealpiggy.com/widgets/ ||nzpages.co.nz^*/banners/ ||o2live.com^$third-party ||oasap.com/images/affiliate/ ||obox-design.com/affiliate-banners/ ||ocp.cbs.com/pacific/request.jsp? ||odin.goo.mx^ ||offers-service.cbsinteractive.com^$third-party ||offerssyndication.appspot.com^$third-party ||office.eteachergroup.com/leads/$third-party ||oilofasia.com/images/banners/ ||ojooo.com/register_f/$third-party ||ojooo.com^*/banner_$third-party ||on.maxspeedcdn.com^ ||onegameplace.com/iframe.php$third-party ||oovoo.com^*/banners/ ||optimus-pm.com^*_300-250.jpg ||origin.getprice.com.au/WidgetNews.aspx ||origin.getprice.com.au/widgetnewssmall.aspx ||oriongadgets.com^*/banners/ ||osobnosti.cz/images/casharena_ ||outdoorhub.com/js/_bookends.min.js ||overseasradio.com/affbanner.php? ||ovpn.to/ovpn.to/banner/ ||ox-i.cordillera.tv^ ||oxygenboutique.com/Linkshare/ ||p.pw/banners/$third-party ||padsdel.com^$third-party ||pagead2.googlesyndication.com^$~object-subrequest ||pagerage.com^$subdocument,third-party ||pan.dogster.com^$third-party ||partner.alloy.com^$third-party ||partner.bargaindomains.com^ ||partner.catchy.com^ ||partner.e-conomic.com^$third-party ||partner.premiumdomains.com^ ||partnerads.ysm.yahoo.com^ ||partnerads1.ysm.yahoo.com^ ||partners.betus.com^$third-party ||partners.dogtime.com/network/ ||partners.fshealth.com^ ||partners.optiontide.com^ ||partners.rochen.com^ ||partners.sportingbet.com.au^ ||partners.vouchedfor.co.uk^ ||partners.xpertmarket.com^ ||paytel.co.za/code/ref ||payza.com/images/banners/ ||pcash.imlive.com^$third-party ||pcmall.co.za/affiliates/ ||pdl.viaplay.com/commercials/$third-party ||pearlriverusa.com/images/banner/ ||perfectforex.biz/images/*x$third-party ||perfectmoney.com/img/banners/$third-party ||ph.hillcountrytexas.com/imp.php?$third-party ||phobos.apple.com^$image,domain=dailymotion.com|youtube.com ||phonephotographytricks.com/images/banners/ ||pianobuyer.com/pianoworld/ ||pianoteq.com/images/banners/ ||pic.pbsrc.com/hpto/ ||picoasis.net/3xlayer.htm ||pics.firstload.de^$third-party ||play-asia.com/paos-$third-party ||playata.myvideo.de^$subdocument,third-party ||player.screenwavemedia.com^*/ova-jw.swf$object-subrequest ||playfooty.tv/jojo.html ||plexidigest.com/plexidigest-300x300.jpg ||pm.web.com^$third-party ||pokerjunkie.com/rss/ ||pokerroomkings.com^*/banner/$third-party ||pokersavvy.com^*/banners/ ||pokerstars.com/?source=$subdocument,third-party ||pokerstars.com/euro_bnrs/ ||popeoftheplayers.eu/ad ||popmog.com^$third-party ||pops.freeze.com^$third-party ||pornturbo.com/tmarket.php ||post.rmbn.ru^$third-party ||postaffiliatepro.com^*/banners/$image ||ppc-coach.com/jamaffiliates/ ||premium-template.com/banner/$third-party ||premium.naturalnews.tv^$third-party ||pricedinfo.com^$third-party ||pricegrabber.com/cb_table.php$third-party ||pricegrabber.com/export_feeds.php?$third-party ||pricegrabber.com/mlink.php?$third-party ||pricegrabber.com/mlink3.php?$third-party ||priceinfo.comuv.com^ ||primeloopstracking.com/affil/ ||privatewifi.com/swf/banners/ ||prizerebel.com/images/banner$third-party ||pro-gmedia.com^*/skins/ ||promos.fling.com^ ||promote.pair.com^ ||promotions.iasbet.com^ ||propgoluxury.com/partners/$third-party ||proxies2u.com/images/btn/$third-party ||proxy.org/blasts.gif ||proxynoid.com/images/referrals/ ||proxyroll.com/proxybanner.php ||proxysolutions.net/affiliates/ ||pub.aujourdhui.com^$third-party ||pub.betclick.com^ ||pub.dreamboxcart.com^$third-party ||pub.sapo.pt/vast.php$object-subrequest ||public.porn.fr^$third-party ||pubs.hiddennetwork.com^ ||puntersparadise.com.au/banners/ ||purevpn.com/affiliates/ ||putlocker.com/images/banners/$third-party ||qualoo.net/now/interstitial/ ||quickflix*.gridserver.com^$third-party ||quirk.biz/webtracking/ ||racebets.com/media.php? ||rack.bauermedia.co.uk^ ||rackcdn.com/brokers/$third-party,domain=fxempire.com|fxempire.de|fxempire.it|fxempire.nl ||rackcdn.com^$script,domain=search.aol.com ||rackspacecloud.com/Broker%20Buttons/$domain=investing.com ||radiocentre.ca/randomimages/$third-party ||radioreference.com/sm/300x75_v3.jpg ||radioshack.com^*/promo/ ||radiotown.com/splash/images/*_960x600_ ||radley.co.uk^*/Affiliate/ ||rapidgator.net/images/pics/*_300%D1%85250_ ||rapidjazz.com/banner_rotation/ ||ratesupermarket.ca/widgets/ ||rbth.ru/widget/$third-party ||rcm*.amazon.$third-party ||rdio.com/media/images/affiliate/$third-party ||readme.ru/informer/$third-party ||realwritingjobs.com^*/banners/ ||red-tube.com^*.php?wmid=*&kamid=*&wsid=$third-party ||redbeacon.com/widget/$third-party ||redflagdeals.com/dealoftheday/widgets/$third-party ||redtram.com^$script,third-party ||regmyudid.com^*/index.html$third-party ||regnow.com/vendor/ ||rehost.to/?ref= ||relink.us/images/$third-party ||res3.feedsportal.com^ ||resources.heavenmedia.net/selection.php? ||revealads.appspot.com^ ||rewards1.com/images/referralbanners/$third-party ||ribbon.india.com^$third-party ||richmedia.yahoo.com^$third-party ||roadcomponentsdb.com^$subdocument,third-party ||roadrecord.co.uk/widget.js? ||roia.hutchmedia.com^$third-party ||roshansports.com/iframe.php ||roshantv.com/adad. ||rotabanner.kulichki.net^ ||rover.ebay.com^*&adtype=$third-party ||runerich.com/images/sty_img/runerich.gif ||ruralpressevents.com/agquip/logos/$domain=farmonline.com.au ||russian-dreams.net/static/js/$third-party ||rya.rockyou.com^$third-party ||s-assets.tp-cdn.com/widgets/*/vwid/*.html? ||s-yoolk-banner-assets.yoolk.com^ ||s-yoolk-billboard-assets.yoolk.com^ ||s.cxt.ms^$third-party ||s1.wp.com^$subdocument,third-party ||s11clickmoviedownloadercom.maynemyltf.netdna-cdn.com^$third-party ||s1now.com^*/takeovers/ ||s3.amazonaws.com/draftset/banners/ ||safarinow.com/affiliate-zone/ ||sailthru.com^*/horizon.js ||salemwebnetwork.com/Stations/images/SiteWrapper/ ||sat-shop.co.uk/images/$third-party ||satshop.tv/images/banner/$third-party ||schenkelklopfer.org^*pop.js ||schurzdigital.com/deals/widget/ ||sciencecareers.org/widget/$third-party ||scoopdragon.com/images/Goodgame-Empire-MPU.jpg ||screenconnect.com/miscellaneous/ScreenConnect-$image,third-party ||scribol.com/txwidget$third-party ||searchportal.information.com/?$third-party ||secondspin.com/twcontent/ ||securep2p.com^$subdocument,third-party ||secureupload.eu/banners/ ||seedboxco.net/*.swf$third-party ||seedsman.com/affiliate/$third-party ||selectperformers.com/images/a/ ||selectperformers.com/images/elements/bannercolours/ ||servedby.keygamesnetwork.com^ ||servedby.yell.com^$third-party ||server.freegamesall.com^$third-party ||server4.pro/images/banner.jpg ||service.smscoin.com/js/sendpic.js ||serving.portal.dmflex.com^$domain=thisdaylive.com ||settleships.com^$third-party ||sfimg.com/images/banners/ ||sfimg.com/SFIBanners/ ||sfm-offshore.com/images/banners/ ||sfstatic.com^*/js/fl.js$third-party ||shaadi.com^*/get-banner.php? ||shaadi.com^*/get-html-banner.php? ||shareflare.net/images/$third-party ||shariahprogram.ca/banners/ ||sharingzone.net/images/banner$third-party ||shop-top1000.com/images/ ||shop4tech.com^*/banner/ ||shopbrazos.com/widgets/ ||shopilize.com^$third-party ||shopping.com/sc/pac/sdc_widget_v2.0_proxy.js$third-party ||shorte.st/link-converter.min.js ||shorte.st^*/referral_banners/ ||shows-tv.net/codepopup.js ||shragle.com^*?ref= ||sidekickunlock.net/banner/ ||simplifydigital.co.uk^*/widget_premium_bb.htm ||simplyfwd.com/?dn=*&pid=$subdocument ||singlehop.com/affiliates/$third-party ||singlemuslim.com/affiliates/ ||sis.amazon.com/iu?$third-party ||sisters-magazine.com/iframebanners/$third-party ||site5.com/creative/$third-party ||site5.com/creative/*/234x60.gif ||sitegrip.com^*/swagbucks- ||skydsl.eu/banner/$third-party ||slickdeals.meritline.com^$third-party ||slot.union.ucweb.com^ ||slysoft.com/img/banner/$third-party ||smart.styria-digital.com^ ||smartdestinations.com/ai/$third-party ||smartlinks.dianomi.com^$third-party ||smilepk.com/bnrsbtns/ ||snacktools.net/bannersnack/ ||snapapp.com^$third-party,domain=bostonmagazine.com ||snapdeal.com^*.php$third-party ||sndkorea.nowcdn.co.kr^$third-party ||socialmonkee.com/images/$third-party ||socialorganicleads.com/interstitial/ ||softneo.com/popup.js ||speedbit.com^*-banner1- ||speedppc.com^*/banners/ ||speedtv.com.edgesuite.net/img/static/takeovers/ ||spilcdn.com/vda/css/sgadfamily.css ||spilcdn.com/vda/css/sgadfamily2.css ||spilcdn.com/vda/vendor/flowplayer/ova.swf ||splashpagemaker.com/images/$third-party ||sponsorandwin.com/images/banner- ||sportingbet.com.au/sbacontent/puntersparadise.html ||sportsbetaffiliates.com.au^$third-party ||sportsdigitalcontent.com/betting/ ||sproutnova.com/serve.php$third-party ||squarespace.evyy.net^ ||srv.dynamicyield.com^$third-party ||srwww1.com^*/affiliate/ ||ssl-images-amazon.com/images/*/banner/$third-party ||ssshoesss.ro/banners/ ||stacksocial.com/bundles/$third-party ||stacksocial.com^*?aid=$third-party ||stalliongold.com/images/*x$third-party ||stargames.com/bridge.asp?$third-party ||static.multiplayuk.com/images/w/w- ||static.tumblr.com/dhqhfum/WgAn39721/cfh_header_banner_v2.jpg ||staticworld.net/images/*_skin_ ||stats.hosting24.com^ ||stats.sitesuite.org^ ||storage.to/affiliate/ ||streamtheworld.com/ondemand/ars?type=preroll$object-subrequest ||streamtheworld.com/ondemand/creative? ||strikeadcdn.s3.amazonaws.com^$third-party ||structuredchannel.com/sw/swchannel/images/MarketingAssets/*/BannerAd ||stylefind.com^*?campaign=$subdocument,third-party ||subliminalmp3s.com^*/banners/ ||superherostuff.com/pages/cbmpage.aspx?*&cbmid=$subdocument,third-party ||supersport.co.za^*180x254 ||supersport.com/content/2014_Sponsor ||supersport.com/content/Sponsors ||supply.upjers.com^$third-party ||surf100sites.com/images/banner_ ||surveymonkey.com/jspop.aspx?$third-party ||surveywriter.net^$script,third-party ||survivaltop50.com/wp-content/uploads/*/Survival215x150Link.png ||svcs.ebay.com/services/search/FindingService/*^affiliate.tracking$third-party ||swarmjam.com^$script,third-party ||sweed.to/?pid=$third-party ||sweed.to/affiliates/ ||sweetwater.com/feature/$third-party ||sweeva.com/widget.php?w=$third-party ||swimg.net^*/banners/ ||syndicate.payloadz.com^$third-party ||syndication.jsadapi.com^ ||syndication.visualthesaurus.com/std/vtad.js ||syndication1.viraladnetwork.net^ ||tag.regieci.com^$third-party ||take2.co.za/misc/bannerscript.php? ||takeover.bauermedia.co.uk^$~stylesheet ||talkfusion.com^*/banners/ ||tankionline.com/tankiref.swf ||tap.more-results.net^ ||techbargains.com/inc_iframe_deals_feed.cfm?$third-party ||techbargains.com/scripts/banner.js$third-party ||tedswoodworking.com/images/banners/ ||textlinks.com/images/banners/ ||thaiforlove.com/userfiles/affb- ||thatfreething.com/images/banners/ ||theatm.info/images/$third-party ||thebigchair.com.au^$subdocument,third-party ||themes420.com/bnrsbtns/ ||themify.me/banners/$third-party ||themis-media.com^*/sponsorships/ ||thereadystore.com/affiliate/ ||theseblogs.com/visitScript/ ||theseforums.com/visitScript/ ||theselfdefenseco.com/?affid=$third-party ||thetechnologyblog.net^*/bp_internet/ ||thirdpartycdn.lumovies.com^$third-party ||ti.tradetracker.net^ ||ticketkai.com/banner/ ||ticketmaster.com/promotionalcontent/ ||tickles.co.uk^$subdocument,third-party ||tickles.ie^$subdocument,third-party ||tigerdirect.com^*/affiliate_ ||tinyurl.com/4x848hd$subdocument ||tipico.*/affiliate/$third-party ||tipico.*?affiliateId=$third-party ||tiqiq.com/Tiqiq/WidgetInactiveIFrame.aspx?WidgetID=*&PublisherID=$subdocument,third-party ||tmbattle.com/images/promo_ ||tmz.vo.llnwd.net^*_rightrail_200x987.swf ||todaysfinder.com^$subdocument,third-party ||tonefuse.s3.amazonaws.com/clientjs/ ||top5result.com/promo/ ||topbinaryaffiliates.ck-cdn.com^$third-party ||topmedia.com/external/ ||topspin.net/secure/media/$image,domain=youtube.com ||toptenreviews.com/r/c/ ||toptenreviews.com/w/af_widget.js$third-party ||torguard.net/images/aff/ ||tosol.co.uk/international.php?$third-party ||townnews.com^*/dealwidget.css? ||townnews.com^*/upickem-deals.js? ||townsquareblogs.com^*=sponsor& ||toysrus.com/graphics/promo/ ||traceybell.co.uk^$subdocument,third-party ||track.bcvcmedia.com^ ||tradeboss.com/1/banners/ ||travelmail.traveltek.net^$third-party ||travelplus.tv^$third-party,domain=kissanime.com ||treatme.co.nz/Affiliates/ ||tremormedia.com/embed/js/*_ads.js ||tremormedia.com^*/tpacudeoplugin46.swf ||tremormedia.com^*_preroll_ ||trialpay.com^*&dw-ptid=$third-party ||tribktla.files.wordpress.com/*-639x125-sponsorship.jpg? ||tribwgnam.files.wordpress.com^*reskin2. ||tripadvisor.com/WidgetEmbed-*&partnerId=$domain=rbth.co.uk|rbth.com ||tritondigital.com/lt?sid*&hasads= ||tritondigital.com/ltflash.php? ||trivago.co.uk/uk/srv/$third-party ||tshirthell.com/img/affiliate_section/$third-party ||ttt.co.uk/TMConverter/$third-party ||turbobit.net/ref/$third-party ||turbobit.net/refers/$third-party ||turbotrafficsystem.com^*/banners/ ||turner.com^*/promos/ ||twinplan.com^ ||twivert.com/external/banner234x60. ||u-loader.com/image/hotspot_ ||ubuntudeal.co.za^$subdocument,third-party ||ukcast.tv/adds/ ||ukrd.com/image/*-160x133.jpg ||ukrd.com/image/*-160x160.png ||ukrd.com/images/icons/amazon.png ||ukrd.com/images/icons/itunes.png ||ultimatewebtraffic.info/images/fbautocash ||uniblue.com^*/affiliates/ ||united-domains.de/parking/ ||united-domains.de^*/parking/ ||unsereuni.at/resources/img/$third-party ||upickem.net^*/affiliates/$third-party ||upload2.com/upload2.html ||uploaded.net/img/public/$third-party ||uploaded.to/img/public/$third-party ||uploaded.to/js/layer.js ||uploadstation.com/images/banners/ ||urtig.net/scripts/js3caf.js ||usenet.pw^$third-party ||usenetbucket.com^*-banner/ ||usersfiles.com/images/72890UF.png ||usfine.com/images/sty_img/usfine.gif ||ussearch.com/preview/banner/ ||valuechecker.co.uk/banners/$third-party ||vcnewsdaily.com/images/vcnews_right_banner.gif ||vdownloader.com/pages/$subdocument,third-party ||vendor1.fitschigogerl.com^ ||veospot.com^*.html ||viagogo.co.uk/feeds/widget.ashx? ||videoweed.es/js/aff.js ||videozr.com^$third-party ||vidible.tv/placement/vast/ ||vidible.tv/prod/tags/$third-party ||vidyoda.com/fambaa/chnls/ADSgmts.ashx? ||viglink.com/api/batch^$third-party ||viglink.com/api/insert^$third-party ||viglink.com/api/optimize^$third-party ||viglink.com/api/products^$third-party ||virool.com/widgets/$third-party ||virtuagirl.com/ref.php? ||virtuaguyhd.com/ref.php? ||visit.homepagle.com^$third-party ||visitorboost.com/images/$third-party ||vitabase.com/images/relationships/$third-party ||vittgam.net/images/b/ ||voodoo.com^$third-party ||vpn4all.com^*/banner/ ||vpntunnel.se/aff/$third-party ||vpnxs.nl/images/vpnxs_banner ||vrvm.com/t? ||vuvuplaza.com^$subdocument,third-party ||vxite.com/banner/ ||vze.com^$domain=uploadlw.com ||walmartimages.com^*/HealthPartner_ ||warezhaven.org/warezhavenbann.jpg ||warrantydirect.co.uk/widgets/ ||washingtonpost.com/wp-srv/wapolabs/dw/readomniturecookie.html ||watch-free-movie-online.net/adds- ||watch-naruto.tv/images/$third-party ||watchme.com/track/$subdocument,third-party ||watersoul.com^$subdocument,third-party ||wealthyrush.com^*/banners/$third-party ||weatherthreat.com^*/app_add.png ||web-jp.ad-v.jp^ ||web2feel.com/images/$third-party ||webdev.co.zw/images/banners/$third-party ||webmasterrock.com/cpxt_pab ||website.ws^*/banners/ ||whistleout.s3.amazonaws.com^ ||widgeo.net/popup.js ||widget.cheki.com.ng^$third-party ||widget.crowdignite.com^ ||widget.imshopping.com^$third-party ||widget.jobberman.com^$third-party ||widget.kelkoo.com^ ||widget.raaze.com^ ||widget.scoutpa.com^$third-party ||widget.searchschoolsnetwork.com^ ||widget.shopstyle.com.au^ ||widget.shopstyle.com/widget?pid=$subdocument,third-party ||widget.solarquotes.com.au^ ||widgetcf.adviceiq.com^$third-party ||widgets.adviceiq.com^$third-party ||widgets.fie.futurecdn.net^$script ||widgets.itunes.apple.com^*&affiliate_id=$third-party ||widgets.mobilelocalnews.com^$third-party ||widgets.mozo.com.au^$third-party ||widgets.privateproperty.com.ng^$third-party ||widgets.progrids.com^$third-party ||widgets.realestate.com.au^ ||wildamaginations.com/mdm/banner/ ||winpalace.com/?affid= ||winsms.co.za/banner/ ||wishlistproducts.com/affiliatetools/$third-party ||wm.co.za/24com.php? ||wm.co.za/wmjs.php? ||wonderlabs.com/affiliate_pro/banners/ ||worldcdn.net^*/banners/ ||worldnow.com/images/incoming/RTJ/rtj201303fall.jpg ||worldofjudaica.com/products/dynamic_banner/ ||worldofjudaica.com/static/show/external/ ||wp.com^*/linkwidgets/$domain=coedmagazine.com ||wrapper.ign.com^$third-party ||ws.amazon.*/widgets/$third-party ||wsockd.com^$third-party ||wtpn.twenga.co.uk^ ||wtpn.twenga.de^ ||wtprn.com/images/$domain=rprradio.com ||wtprn.com/sponsors/ ||wupload.com/images/banners/ ||wupload.com/referral/$third-party ||x3cms.com/ads/ ||xcams.com/livecams/pub_collante/script.php?$third-party ||xgaming.com/rotate*.php?$third-party ||xigen.co.uk^*/Affiliate/ ||xingcloud.com^*/uid_ ||xml.exactseek.com/cgi-bin/js-feed.cgi?$third-party ||xproxyhost.com/images/banners/ ||yachting.org^*/banner/ ||yahoo.net^*/ads/ ||yb.torchbrowser.com^ ||yeas.yahoo.co.jp^ ||yieldmanager.edgesuite.net^$third-party ||yimg.com/gs/apex/mediastore/ ||yimg.com^*/dianominewwidget2.html$domain=yahoo.com ||yimg.com^*/quickplay_maxwellhouse.png ||yimg.com^*/sponsored.js ||yimg.com^*_skin_$domain=yahoo.com ||ynet.co.il^*/ynetbanneradmin/ ||yontoo.com^$subdocument,third-party ||yooclick.com^$subdocument,third-party ||you-cubez.com/images/banners/ ||zapads.zapak.com^ ||zazzle.com/utl/getpanel$third-party ||zazzle.com^*?rf$third-party ||zergnet.com/zerg.js$third-party ||zeus.qj.net^ ||zeusfiles.com/promo/ ||ziffdavisenterprise.com/contextclicks/ ||ziffprod.com/CSE/BestPrice? ||zip2save.com/widget.php? ||zmh.zope.net^$third-party ||zoomin.tv/video/*.flv$third-party,domain=twitch.tv ! Mobile ||iadc.qwapi.com^ ! Anti-Adblock ! *** easylist:easylist/easylist_thirdparty_popup.txt *** ||4utro.ru^$popup ||5.39.67.191/promo.php?$popup ||6angebot.ch/?ref=$popup,third-party ||adfoc.us/serve/$popup,third-party ||admngronline.com^$popup,third-party ||adrotator.se^$popup ||adserving.unibet.com^$popup,third-party ||affiliates.galapartners.co.uk^$popup,third-party ||affportal-lb.bevomedia.com^$popup,third-party ||amazing-offers.co.il^$popup,third-party ||babylon.com/redirects/$popup,third-party ||babylon.com/welcome/index.html?affID=$popup,third-party ||banner.galabingo.com^$popup,third-party ||bet365.com^*affiliate=$popup ||binaryoptions24h.com^$popup,third-party ||bovada.lv^$popup,third-party ||casino.com^*?*=$popup,third-party ||casinoadviser.net^$popup ||cdn.optmd.com^$popup,third-party ||chatlivejasmin.net^$popup ||chatulfetelor.net/$popup ||chaturbate.com/affiliates/$popup,third-party ||click.scour.com^$popup,third-party ||clickansave.net^$popup,third-party ||ctcautobody.com^$popup,third-party ||d1110e4.se^$popup ||dateoffer.net/?s=*&subid=$popup,third-party ||eroticmix.blogspot.$popup ||erotikdeal.com/?ref=$popup,third-party ||erotikdeal.com/advertising.html$popup,third-party ||eurogrand.com^$popup ||europacasino.com^$popup,third-party ||evanetwork.com^$popup ||facebookcoverx.com^$popup,third-party ||fastclick.net^$popup ||firstload.com^$popup ||firstload.de^$popup ||flashplayer-updates.com^$popup ||fleshlight.com/?link=$popup,third-party ||free-rewards.com-s.tv^$popup ||fsoft4down.com^$popup ||fulltiltpoker.com/?key=$popup,third-party ||fulltiltpoker.com/affiliates/$popup,third-party ||fwmrm.net/ad/$popup ||generic4all.com^*.dhtml?refid=$popup,third-party ||getsecuredfiles.com^$popup,third-party ||hdvid-codec.com^$popup ||hdvidcodecs.com^$popup ||hetu.in^$popup,third-party ||homemadecelebrityporn.com/track/$popup,third-party ||hyperlinksecure.com/back?token=$popup ||hyperlinksecure.com/go/$popup ||i2casting.com^$popup,third-party ||itunes.apple.com^$popup,domain=fillinn.com ||liutilities.com^*/affiliate/$popup ||lovefilm.com/partners/$popup,third-party ||lovepoker.de^*/?pid=$popup ||lp.ilivid.com/?$popup,third-party ||lp.imesh.com/?$popup,third-party ||lp.titanpoker.com^$popup,third-party ||lsbet.com/bonus/$popup,third-party ||lumosity.com/landing_pages/$popup ||lyricsbogie.com/?$popup,third-party ||makemoneyonline.2yu.in^$popup ||maxedtube.com/video_play?*&utm_campaign=$popup,third-party ||mcars.org/landing/$popup,third-party ||media.mybet.com/redirect.aspx?pid=*&bid=$popup,third-party ||megacloud.com/signup?$popup,third-party ||meme.smhlmao.com^$popup,third-party ||mgid.com^$popup,third-party ||mypromocenter.com^$popup ||noowmedia.com^$popup ||opendownloadmanager.com^$popup,third-party ||otvetus.com^$popup,third-party ||paid.outbrain.com/network/redir?$popup,third-party ||planet49.com/cgi-bin/wingame.pl?$popup ||platinumdown.com^$popup ||pokerstars.eu^*/?source=$popup,third-party ||priceinfo.comuv.com^$popup ||promo.galabingo.com^$popup,third-party ||promo.xcasino.com/?$popup,third-party ||pub.ezanga.com/rv2.php?$popup ||rackcorp.com^$popup ||record.sportsbetaffiliates.com.au^$popup,third-party ||red-tube.com/popunder/$popup ||rocketgames.com^$popup,third-party ||roomkey.com/referrals?$popup,third-party ||secure.komli.com^$popup,third-party ||serve.prestigecasino.com^$popup,third-party ||serve.williamhillcasino.com^$popup,third-party ||settlecruise.org^$popup ||sharecash.org^$popup,third-party ||softingo.com/clp/$popup ||stake7.com^*?a_aid=$popup,third-party ||stargames.com/bridge.asp?idr=$popup ||stargames.com/web/*&cid=*&pid=$popup,third-party ||sunmaker.com^*^a_aid^$popup,third-party ||thebestbookies.com^$popup,domain=firstrow1us.eu ||theseforums.com^*/?ref=$popup ||thetraderinpajamas.com^$popup,third-party ||tipico.com^*?affiliateid=$popup,third-party ||torntv-tvv.org^$popup,third-party ||track.mypcbackup.com^$popup,third-party ||track.xtrasize.nl^$popup,third-party ||tripadvisor.*/HotelLander?$popup,third-party ||truckingunlimited.com^$popup,domain=sharpfile.com ||ul.to/ref/$popup ||upbcd.info/vuze/$popup ||uploaded.net/ref/$popup ||urlcash.net/random*.php$popup ||urmediazone.com/play?ref=$popup,third-party ||usenet.nl^$popup ||vidds.net/?s=promo$popup,third-party ||wealth-at-home-millions.com^$popup,third-party ||weeklyprizewinner.com-net.info^$popup ||with-binaryoption.com^$popup,third-party ||withbinaryoptions.com^$popup,third-party ||wptpoker.com^$popup ! *** easylist:easylist_adult/adult_thirdparty.txt *** .php?pub=*&trw_adblocker=$subdocument /exports/livemodel/?$subdocument ||193.34.134.18^*/banners/ ||193.34.134.74^*/banners/ ||204.140.25.247/ads/ ||213.174.130.10/banners/ ||213.174.130.8/banners/ ||213.174.130.9/banners/ ||213.174.140.76/js/showbanner4.js ||213.174.140.76^*/ads/ ||213.174.140.76^*/js/msn-$script ||213.174.140.76^*/js/msn.js ||4tube.com/iframe/$third-party ||79.120.183.166^*/banners/ ||88.208.23.$third-party,domain=xhamster.com ||88.85.77.94/rotation/$third-party ||91.83.237.41^*/banners/ ||a.sucksex.com^$third-party ||ad.duga.jp^ ||ad.favod.net^$third-party ||ad.iloveinterracial.com^ ||ad.traffmonster.info^$third-party ||adb.fling.com^$third-party ||ads.contentabc.com^$third-party ||ads.videosz.com^ ||adsrv.bangbros.com^$third-party ||adtools.gossipkings.com^$third-party ||adtools2.amakings.com^$third-party ||adultdvd.com/plugins/*/store.html$third-party ||adultfax.com/service/vsab.php? ||adultfriendfinder.com/go/$third-party ||adultfriendfinder.com/images/banners/$third-party ||adultfriendfinder.com/javascript/$third-party ||adultfriendfinder.com/piclist?$third-party ||adultporntubemovies.com/images/banners/ ||aebn.net/banners/ ||aebn.net/feed/$third-party ||aff-jp.dxlive.com^$third-party ||aff-jp.exshot.com^$third-party ||affiliate.burn-out.tv^$third-party ||affiliate.dtiserv.com^$third-party ||affiliate.godaddy.com^$third-party ||affiliates.cupidplc.com^$third-party ||affiliates.easydate.biz^$third-party ||affiliates.franchisegator.com^$third-party ||affiliates.thrixxx.com^ ||allanalpass.com/visitScript/ ||alt.com/go/$third-party ||amarotic.com/Banner/$third-party ||amarotic.com/rotation/layer/chatpage/$third-party ||amarotic.com^*?wmid=*&kamid=*&wsid=$third-party ||amateur.amarotic.com^$third-party ||amateurseite.com/banner/$third-party ||ambya.com/potdc/ ||ard.sweetdiscreet.com^ ||asianbutterflies.com/potd/ ||asktiava.com/promotion/ ||assinclusive.com/cyonix.html ||assinclusive.com/linkstxt2.html ||atlasfiles.com^*/sp3_ep.js$third-party ||avatraffic.com/b/ ||b.turbo.az^$third-party ||babes.picrush.com^$third-party ||banner.69stream.com^$third-party ||banner.gasuki.com^$third-party ||banner.resulthost.org^$third-party ||banner.themediaplanets.com^$third-party ||banners*.spacash.com^$third-party ||banners.adultfriendfinder.com^$third-party ||banners.alt.com^$third-party ||banners.amigos.com^$third-party ||banners.blacksexmatch.com^$third-party ||banners.fastcupid.com^$third-party ||banners.fuckbookhookups.com^$third-party ||banners.nostringsattached.com^$third-party ||banners.outpersonals.com^$third-party ||banners.passion.com^$third-party ||banners.passiondollars.com^$third-party ||banners.payserve.com^$third-party ||banners.penthouse.com^$third-party ||banners.rude.com^$third-party ||banners.rushcommerce.com^$third-party ||banners.videosecrets.com^$third-party ||banners.webcams.com^$third-party ||bannershotlink.perfectgonzo.com^ ||bans.bride.ru^$third-party ||bbp.brazzers.com^$third-party ||bigmovies.com/images/banners/ ||blaaaa12.googlecode.com^ ||blackbrazilianshemales.com/bbs/banners/ ||blogspot.com^*/ad.jpg ||bongacash.com/promo.php ||bongacash.com/tools/promo.php$third-party ||br.blackfling.com^ ||br.fling.com^ ||br.realitykings.com^ ||brasileirinhas.com.br/banners/ ||brazzers.com/ads/ ||bullz-eye.com/pictureofday/$third-party ||cache.worldfriends.tv^$third-party ||camelmedia.net/thumbs/$third-party ||cams.com/go/$third-party ||cams.com/p/cams/cpcs/streaminfo.cgi?$third-party ||cams.enjoy.be^$third-party ||cams.spacash.com^$third-party ||camsrule.com/exports/$third-party ||cartoontube.com^$subdocument,third-party ||cash.femjoy.com^$third-party ||cdn.epom.com^*/940_250.gif ||cdncache2-a.akamaihd.net^$third-party ||cdnjke.com^$third-party ||chaturbate.com/affiliates/ ||chaturbate.com/creative/ ||click.absoluteagency.com^$third-party ||click.kink.com^$third-party ||clickz.lonelycheatingwives.com^$third-party ||clipjunkie.com/sftopbanner$third-party ||closepics.com/media/banners/ ||cmix.org/teasers/? ||cockfortwo.com/track/$third-party ||content.liveuniverse.com^$third-party ||contentcache-a.akamaihd.net^$third-party ||cp.intl.match.com^$third-party ||cpm.amateurcommunity.com^ ||creamgoodies.com/potd/ ||crocogirls.com/croco-new.js ||cs.celebbusters.com^$third-party ||cs.exposedontape.com^$third-party ||dailyvideo.securejoin.com^ ||daredorm.com^$subdocument,third-party ||datefree.com^$third-party ||ddfcash.com/iframes/$third-party ||ddfcash.com/promo/banners/ ||ddstatic.com^*/banners/ ||desk.cmix.org^ ||devilgirls.co/images/devil.gif ||devilgirls.co/pop.js ||dom2xxx.com/ban/$third-party ||downloadsmais.com/imagens/download-direto.gif ||dump1.no-ip.biz^$third-party ||dvdbox.com/promo/$third-party ||eliterotica.com/images/banners/ ||erotikdeal.com/?ref=$third-party ||escortforum.net/images/banners/$third-party ||eurolive.com/?module=public_eurolive_onlinehostess& ||eurolive.com/index.php?module=public_eurolive_onlinetool& ||evilangel.com/static/$third-party ||exposedemos.com/track/$third-party ||exposedteencelebs.com/banner/$third-party ||extremeladyboys.com/elb/banners/ ||f5porn.com/porn.gif ||fansign.streamray.com^$third-party ||fastcdn.me/js/snpp/ ||fastcdn.me/mlr/ ||fbooksluts.com^$subdocument,third-party ||fckya.com/lj.js ||feeds.videosz.com^ ||femjoy.com/bnrs/$third-party ||ff.nsg.org.ua^ ||firestormmedia.tv^*?affid= ||fleshlight.com/images/banners/ ||fleshlight.com/images/peel/ ||freebbw.com/webcams.html$third-party ||freeonescams.com^$subdocument,third-party ||freeporn.hu/banners/ ||freexxxvideoclip.aebn.net^ ||freshnews.su/get_tizers.php? ||fuckhub.net^*?pid=$third-party ||gagthebitch.com/track/$third-party ||galeriaseroticas.xpg.com.br^$third-party ||galleries.videosz.com^$object,third-party ||gallery.deskbabes.com^*.php?dir=*&ids=$third-party ||gammasites.com/pornication/pc_browsable.php? ||gateway-banner.eravage.com^$third-party ||geo.camazon.com^$third-party ||geo.cliphunter.com^ ||geobanner.adultfriendfinder.com^ ||geobanner.alt.com^ ||geobanner.blacksexmatch.com^$third-party ||geobanner.fuckbookhookups.com^$third-party ||geobanner.sexfinder.com^$third-party ||geobanner.socialflirt.com^ ||gfrevenge.com/vbanners/ ||girls-home-alone.com/dating/ ||go2cdn.org/brand/$third-party ||graphics.pop6.com/javascript/$script,third-party,domain=~adultfriendfinder.co.uk|~adultfriendfinder.com ||graphics.streamray.com^*/cams_live.swf$third-party ||hardbritlads.com/banner/ ||hardcoresexnow.com^$subdocument,third-party ||hdpornphotos.com/images/728x180_ ||hdpornphotos.com/images/banner_ ||hentaijunkie.com^*/banners/ ||hentaikey.com/images/banners/ ||highrollercams.com/widgets/$third-party ||hodun.ru/files/promo/ ||homoactive.tv/banner/ ||hoptopboy.com/js/fl.js ||hornybirds.com^$subdocument,third-party ||hornypharaoh.com/banner_$third-party ||hostave3.net/hvw/banners/ ||hosted.x-art.com/potd$third-party ||hosting24.com/images/banners/$third-party ||hotcaracum.com/banner/ ||hotkinkyjo.xxx/resseler/banners/ ||hotmovies.com/custom_videos.php? ||hotsocialz.com^$third-party ||iframe.adultfriendfinder.com^$third-party ||iframes.hustler.com^$third-party ||ifriends.net^$subdocument,third-party ||ihookup.com/configcreatives/ ||image.cecash.com^$third-party ||image.nsk-sys.com^$third-party ||imageteam.org/upload/big/2014/06/22/53a7181b378cb.png ||interracialbangblog.info/banner.jpg ||interracialbangblog.info^*-ban.png ||ivitrine.buscape.com^$third-party ||js.picsomania.info^$third-party ||just-nude.com/images/ban_$third-party ||justcutegirls.com/banners/$third-party ||kau.li/yad.js ||kenny-glenn.net^*/longbanner_$third-party ||kuntfutube.com/bgbb.gif ||lacyx.com/images/banners/ ||ladyboygoo.com/lbg/banners/ ||latinteencash.com/potd/$third-party ||layers.spacash.com^$third-party ||lb-69.com/pics/ ||links.freeones.com^$third-party ||livejasmin.com^$third-party,domain=~awempire.com ||livesexasian.com^$subdocument,third-party ||llnwd.net^*/takeover_ ||longmint.com/lm/banners/ ||loveme.com^$third-party ||magazine-empire.com/images/pornstarad.jpg ||manager.koocash.fr^$third-party ||manhunt.net/?dm=$third-party ||map.pop6.com^$third-party ||match.com/landing/$third-party ||media.eurolive.com^$third-party ||media.match.com^$third-party ||media.mykocam.com^$third-party ||media.mykodial.com^$third-party ||media.pussycash.com^$third-party ||megacash.warpnet.com.br^$third-party ||metartmoney.com^$third-party ||metartmoney.met-art.com^$third-party ||mofomedia.nl/pop-*.js ||movies.spacash.com^*&th=180x135$script ||mrskin.com/affiliateframe/ ||mrskincdn.com^*/flash/aff/$third-party ||mrvids.com/network/$third-party ||ms.wsex.com^$third-party ||my-dirty-hobby.com/?sub=$third-party ||mycams.com/freechat.php?$third-party ||myexposedgirlfriendz.com/pop/popuppp.js ||myexposedgirlfriendz.com/pop/popuprk.js ||myfreakygf.com/www/click/$third-party ||mykocam.com/js/feeds.js$third-party ||naked.com/promos/$third-party ||nakedshygirls.com/bannerimg/ ||natuko-miracle.com/banner/$third-party ||naughtycdn.com/public/iframes/$third-party ||netvideogirls.com/adultfyi.jpg ||nubiles.net/webmasters/promo/$third-party ||nude.hu/html/$third-party ||nudemix.com/widget/ ||nuvidp.com^$third-party ||odnidoma.com/ban/$third-party ||openadultdirectory.com/banner-$third-party ||orgasmtube.com/js/superP/ ||otcash.com/images/$third-party ||outils.f5biz.com^$third-party ||partner.loveplanet.ru^$third-party ||partners.heart2heartnetwork.$third-party ||partners.pornerbros.com^ ||partners.yobt.com^$third-party ||partners.yobt.tv^$third-party ||paydir.com/images/bnr ||pcash.globalmailer5.com^$third-party ||pinkvisualgames.com/?revid=$third-party ||plugin-x.com/rotaban/ ||pod.manplay.com^$third-party ||pod.xpress.com^$third-party ||pop6.adultfriendfinder.com^$third-party ||pop6.com/banners/$third-party ||pop6.com/javascript/im_box-*.js ||porn2blog.com/wp-content/banners/ ||porndeals.com^$subdocument,third-party ||pornhubpremium.com/relatedpremium/$subdocument,third-party ||pornoh.info^$image,third-party ||pornravage.com/notification/$third-party ||pornstarnetwork.com^*_660x70.jpg ||pornturbo.com/*.php?g=$subdocument,third-party ||pornturbo.com^*.php?*&cmp=$subdocument,third-party ||potd.onlytease.com^$third-party ||prettyincash.com/premade/$third-party ||prime.ms^$domain=primejailbait.com ||privatamateure.com/promotion/ ||private.camz.$third-party ||private.com/banner/ ||profile.bharatmatrimony.com^$third-party ||promo.blackcrush.com^$third-party ||promo.cams.com^$third-party ||promo.pegcweb.com^$third-party ||promo1.webcams.nl^$third-party ||promos.gpniches.com^$third-party ||promos.meetlocals.com^$third-party ||promos.wealthymen.com^$third-party ||ptcdn.mbicash.nl^$third-party ||punterlink.co.uk/images/storage/siteban$third-party ||pussycash.com/content/banners/$third-party ||rabbitporno.com/friends/ ||rabbitporno.com/iframes/$third-party ||rawtubelive.com/exports/$third-party ||realitykings.com/vbanners/ ||red-tube.com/dynbanner.php? ||resimler.randevum.com^$third-party ||rexcams.com/misc/iframes_new/ ||rotci.com/images/rotcibanner.png ||rough-sex-in-russia.com^*/webmaster/$third-party ||rss.dtiserv.com^$third-party ||ruleclaim.web.fc2.com^$third-party ||ruscams.com/promo/ ||russkoexxx.com/ban/$third-party ||s1magnettvcom.maynemyltf.netdna-cdn.com^ ||sabin.free.fr^$third-party ||saboom.com.pccdn.com^*/banner/ ||sadtube.com/chat/$script ||sakuralive.com/dynamicbanner/ ||scoreland.com/banner/ ||screencapturewidget.aebn.net^$third-party ||server140.com^$third-party ||sextronix.*.cdnaccess.com^ ||sextronix.com/b/$third-party ||sextronix.com/images/$third-party ||sextubepromo.com/ubr/ ||sexy.fling.com^$third-party ||sexycams.com/exports/$third-party ||share-image.com/borky/ ||shared.juicybucks.com^$third-party ||shemale.asia/sma/banners/ ||shemalenova.com/smn/banners/ ||shinypics.com/blogbanner/$third-party ||simonscans.com/banner/ ||skeettools.com/custom/$third-party ||sleepgalleries.com/recips/$third-party ||slickcash.com/flash/subtitles_$third-party ||smartmovies.net/promo_$third-party ||smyw.org/smyw_anima_1.gif ||snrcash.com/profilerotator/$third-party ||spacash.com//v2bannerview.php? ||spacash.com/popup/$third-party ||spacash.com/tools/peel/ ||sponsor4cash.de/script/ ||steadybucks.com^*/banners/ ||streamen.com/exports/$third-party ||streamray.com/images/cams/flash/cams_live.swf ||surv.xbizmedia.com^ ||sweet.game-rust.ru^ ||swurve.com/affiliates/ ||target.vivid.com^$third-party ||teendaporn.com/rk.js ||thrixxx.com/affiliates/$image ||thrixxx.com/scripts/show_banner.php? ||thumbs.sunporno.com^$third-party ||thumbs.vstreamcdn.com^*/slider.html ||tlavideo.com/affiliates/$third-party ||tools.gfcash.com^$third-party ||tour.cum-covered-gfs.com^$third-party ||tours.imlive.com^$third-party ||track.xtrasize.nl^$third-party ||trader.erosdlz.com^$third-party ||ts.videosz.com/iframes/ ||tubefck.com^*/adawe.swf ||tumblr.com^*/tumblr_mht2lq0XUC1rmg71eo1_500.gif$domain=stocporn.com ||turbolovervidz.com/fling/ ||twiant.com/img/banners/ ||twilightsex.com^$subdocument,third-party ||updatetube.com/iframes/ ||updatetube.com/updatetube_html/ ||upsellit.com/custom/$third-party ||uramov.info/wav/wavideo.html ||vectorpastel.com^$third-party ||vidz.com/promo_banner/$third-party ||vigrax.pl/banner/ ||viorotica.com^*/banners/ ||virtualhottie2.com/cash/tools/banners/ ||visit-x.net/promo/$third-party ||vodconcepts.com^*/banners/ ||vserv.bc.cdn.bitgravity.com^$third-party ||vzzk.com/uploads/banners/$third-party ||wafflegirl.com/galleries/banner/ ||watchmygf.com/preview/$third-party ||webcams.com/js/im_popup.php? ||webcams.com/misc/iframes_new/ ||webmaster.erotik.com^$third-party ||wendi.com/ipt/$third-party ||wetandpuffy.com/galleries/banners/ ||widgets.comcontent.net^ ||widgetssec.cam-content.com^ ||winkit.info/wink2.js ||xcabin.net/b/$third-party ||xlgirls.com/banner/$third-party ||xnxx.com^$third-party ||xtrasize.pl/banner/ ||xxtu.be^$subdocument,third-party ||xxxoh.com/number/$third-party ||youfck.com^*/adawe.swf ||yplf.com/ram/files/sponsors/ ||ztod.com/flash/wall*.swf ||ztod.com/iframe/third/$subdocument ||zubehost.com/*?zoneid= ! *** easylist:easylist_adult/adult_thirdparty_popup.txt *** ||1800freecams.com^$popup,third-party ||21sextury.com^$popup ||777livecams.com/?id=$popup,third-party ||adultfriendfinder.com/banners/$popup,third-party ||adultfriendfinder.com/go/$popup ||amarotic.com/?$popup,third-party ||amarotic.com^*?wmid=$popup,third-party ||babereporters.info^$popup,domain=viewcube.org ||benaughty.com/aff.php?$popup,third-party ||cam4.com/?$popup ||camcity.com/rtr.php?aid=$popup ||candidvoyeurism.com/ads/$popup ||chaturbate.com/*/?join_overlay=$popup ||chaturbate.com/sitestats/openwindow/$popup ||cpm.amateurcommunity.*?cp=$popup,third-party ||devilsfilm.com/track/go.php?$popup,third-party ||epornerlive.com/index.php?*=punder$popup ||exposedwebcams.com/?token=$popup,third-party ||ext.affaire.com^$popup ||extremefuse.com/out.php?$popup ||fantasti.cc/ajax/gw.php?$popup ||fleshlight-international.eu^*?link=$popup,third-party ||fling.com/enter.php?$popup ||flirt4free.com/_special/pops/$popup,third-party ||fuckbookhookups.com/go/$popup ||fuckbooknet.net/dating/$popup,third-party ||fuckshow.org^*&adr=$popup ||fucktapes.org/fucktube.htm$popup ||get-a-fuck-tonight.com^$popup ||hazeher.com/t1/pps$popup ||hqtubevideos.com/play.html$popup,third-party ||icgirls.com^$popup ||imlive.com/wmaster.ashx?$popup,third-party ||jasmin.com^$popup,third-party ||join.filthydatez.com^$popup,third-party ||join.teamskeet.com/track/$popup,third-party ||join.whitegfs.com^$popup ||judgeporn.com/video_pop.php?$popup ||linkfame.com^*/go.php?$popup,third-party ||livecams.com^$popup ||livejasmin.com^$popup,third-party ||media.campartner.com/index.php?cpID=*&cpMID=$popup,third-party ||media.campartner.com^*?cp=$popup,third-party ||meetlocals.com^*popunder$popup ||mjtlive.com/exports/golive/?lp=*&afno=$popup,third-party ||mydirtyhobby.com/?$popup,third-party ||myfreecams.com/?co_id=$popup ||online.mydirtyhobby.com^*?naff=$popup,third-party ||pomnach.ru^$popup ||pornhub.com^*&utm_campaign=*-pop|$popup ||pornme.com^*.php?ref=$popup,third-party ||porno-onlain.info/top.php$popup ||pornoh.info^$popup ||pornslash.com/cbp.php$popup ||postselfies.com^*?nats=$popup,third-party ||redtube.com/bid/$popup ||rudefinder.com/?$popup,third-party ||seekbang.com/cs/rotator/$popup ||seeme.com^*?aid=*&art=$popup ||sex.com/popunder/$popup ||sexier.com/services/adsredirect.ashx?$popup,third-party ||sexier.com^*_popunder&$popup ||sexsearchcom.com^$popup,third-party ||socialflirt.com/go/$popup,third-party ||streamate.com/landing/$popup ||textad.sexsearch.com^$popup ||topbucks.com/popunder/$popup ||tour.mrskin.com^$popup,third-party ||twistys.com/track/$popup,third-party ||upforit.com/ext.php$popup ||videobox.com/?tid=$popup ||videobox.com/tour/$popup ||videosz.com/search.php$popup,third-party ||videosz.com^*&tracker_id=$popup,third-party ||visit-x.net/cams/*.html?*&s=*&ws=$popup,third-party ||wantlive.com/landing/$popup ||webcams.com^$popup,third-party ||xdating.com/search/$popup,third-party ||xvideoslive.com/?AFNO$popup,third-party ||xvideoslive.com/landing/$popup,third-party ||yuvutu.com^$popup,third-party !----------------------Specific advert blocking filters-----------------------! ! *** easylist:easylist/easylist_specific_block.txt *** .com/b?z=$domain=couchtuner.eu|zzstream.li .com/jquery/*.js?_t=$script,third-party .info/*.js?guid=$script,third-party .info^$script,domain=allmyvideos.net|mediafire.com|mooshare.biz|muchshare.net|royalvids.eu|tvmuse.com|tvmuse.eu|vidspot.net|vidtomp3.com /*;sz=*;ord=$domain=webhostingtalk.com /3market.php?$domain=adf.ly|j.gs|q.gs|u.bb /?placement=$script,domain=sockshare.com /af.php?$subdocument /assets/_takeover/*$domain=deadspin.com|gawker.com|gizmodo.com|io9.com|jalopnik.com|jezebel.com|kotaku.com|lifehacker.com /clickpop.js$domain=miliblog.co.uk /com.js$domain=kinox.to /get/path/.banners.$image,third-party /http://[a-zA-Z0-9]+\.[a-z]+\/.*[a-zA-Z0-9]+/$script,third-party,domain=affluentinvestor.com|alfonzorachel.com|allenbwest.com|allenwestrepublic.com|allthumbsgaming.com|barbwire.com|bighealthreport.com|bulletsfirst.net|clashdaily.com|comicallyincorrect.com|conservativebyte.com|conservativevideos.com|cowboybyte.com|creationrevolution.com|dailysurge.com|dccrimestories.com|drginaloudon.com|drhotze.com|eaglerising.com|freedomoutpost.com|godfatherpolitics.com|instigatornews.com|joeforamerica.com|libertyalliance.com|libertymafia.com|libertyunyielding.com|mediafire.com|menrec.com|nickadamsinamerica.com|patriot.tv|patriotoutdoornews.com|patriotupdate.com|photobucket.com|pitgrit.com|politicaloutcast.com|primewire.ag|promptfile.com|quinhillyer.com|shark-tank.com|stevedeace.com|themattwalshblog.com|therealside.com|tinypic.com|victoriajackson.com|zionica.com /market.php?$domain=adf.ly|u.bb /nexp/dok2v=*/cloudflare/rocket.js$script,domain=ubuntugeek.com /static/js/pop*.js$script,domain=baymirror.com|getpirate.com|livepirate.com|mypiratebay.cl|noncensuram.info|pirateproxy.net|pirateproxy.se|proxicity.info|thepiratebay.se.coevoet.nl|tpb.chezber.org|tpb.ipredator.se|tpb.piraten.lu|tpb.pirateparty.ca|tpb.pirates.ie ?random=$script,domain=allmyvideos.net|mediafire.com|mooshare.biz|muchshare.net|tvmuse.com|tvmuse.eu|vidspot.net ^guid=$script,domain=allmyvideos.net|mediafire.com|mooshare.biz|muchshare.net|tvmuse.com|tvmuse.eu|vidspot.net |http:$subdocument,third-party,domain=2ad.in|ad2links.com|adf.ly|adfoc.us|adv.li|adyou.me|allmyvideos.net|ay.gy|imgmega.com|j.gs|linkbucksmedia.com|q.gs|shr77.com|thevideo.me|u.bb|vidspot.net |http://*.com^*|*$script,third-party,domain=sporcle.com |http://creative.*/smart.js$script,third-party |http://j.gs/omnigy*.swf |http://p.pw^$subdocument |https:$subdocument,third-party,domain=2ad.in|adf.ly|adfoc.us|adjet.biz|adv.li|ay.gy|j.gs|q.gs|u.bb ||0-60mag.com/js/takeover-2.0/ ||04stream.com/NEWAD11.php? ||04stream.com/podddpo.js ||10-fast-fingers.com/quotebattle-ad.png ||100best-free-web-space.com/images/ipage.gif ||1023xlc.com/upload/*_background_ ||1043thefan.com^*_Sponsors/ ||1071radio.com//wp-content/banners/ ||1077thebone.com^*/banners/ ||109.236.82.94^$domain=fileforever.net ||11points.com/images/slack100.jpg ||1320wils.com/assets/images/promo%20banner/ ||1340wcmi.com/images/banners/ ||1430wnav.com/images/300- ||1430wnav.com/images/468- ||1590wcgo.com/images/banners/ ||174.143.241.129^$domain=astalavista.com ||1776coalition.com/wp-content/plugins/sam-images/ ||178.209.48.7^$domain=zerohedge.com ||180upload.com/p1.js ||180upload.com/pir/729.js ||194.14.0.39/pia.png$domain=tokyo-tosho.net|tokyotosho.info|tokyotosho.se ||194.14.0.39/pia_wide.png$domain=tokyo-tosho.net|tokyotosho.info|tokyotosho.se ||1up.com/scripts/takeover.js ||1up.com/vip/vip_games.html ||1up.com^*/promos/ ||209.62.111.179/ad.aspx$domain=pachanyc.com ||212.7.200.164^$domain=wjunction.com ||216.151.186.5^*/serve.php?$domain=sendspace.com ||217.79.184.79^$domain=filmovizija.com ||22lottery.com/images/lm468 ||24hourwristbands.com/*.googleadservices.com/ ||2flashgames.com/img/nfs.gif ||2mfm.org/images/banners/ ||2oceansvibe.com/?custom=takeover ||2pass.co.uk/img/avanquest2013.gif ||360haven.com/forums/*.advertising.com/ ||3dsemulator.org/img/download.png ||3dwallpaperstudio.com/hd_wallpapers.png ||3g.co.uk/fad/ ||3pmpickup.com.au/images/kmart_v2.jpg ||4chan.org/support/ ||4downfiles.com/open1.js ||4fastfile.com/afiliat.png ||4fuckr.com/g/$image ||4fuckr.com/static/*-banner. ||4shared.com/images/label1.gif ||4sysops.com^*.php?unit=main$xmlhttprequest ||5.199.170.67^$domain=ncrypt.in ||50statesclassifieds.com/image.php?size_id=$subdocument ||560theanswer.com/upload/sponsor- ||5min.com^*/banners/ ||5star-shareware.com/scripts/5starads.js ||610kvnu.com*^/sponsors/ ||64.245.1.134/search/v2/jsp/pcwframe.jsp?provider= ||6waves.com/aff.php? ||74.86.208.249^$domain=fijivillage.com ||810varsity.com^*/background- ||84.234.22.104/ads/$domain=tvcatchup.com ||85.17.254.150^*.php?$domain=wiretarget.com ||88.80.16.183/streams/counters/ ||8a.nu/site2/sponsors/ ||8a.nu/sponsors/ ||911tabs.com/img/bgd_911tabs_ ||911tabs.com/img/takeover_app_ ||911tabs.com^*/ringtones_overlay.js ||977music.com/index.php?p=get_loading_banner ||977rocks.com/images/300- ||980wcap.com/sponsorlogos/ ||9news.com/promo/ ||a.cdngeek.net^ ||a.giantrealm.com^ ||a.i-sgcm.com^ ||a.kat.ph^ ||a.kickass. ||a.kickasstorrent.me^ ||a.kickassunblock.info^ ||a.kickassunblock.net^ ||a7.org/info/ ||aaugh.com/images/dreamhostad.gif ||abc.com/abcvideo/*/mp4/*_Promo_$object-subrequest,domain=abc.go.com ||abduzeedo.com^*/mt-banner.jpg ||abook.ws/banner6.png ||abook.ws/pyload.png ||abook.ws/th_mydl.gif ||about.com/0g/$subdocument ||aboutmyarea.co.uk/images/imgstore/ ||aboutmyip.com/images/Ad0 ||aboutmyip.com/images/SynaManBanner.gif ||abovetopsecret.com/160_ ||abovetopsecret.com/300_ ||abovetopsecret.com/728_ ||abovetopsecret.com/images/plexidigest-300x300.jpg ||absolutcheats.com/images/changemy*.gif ||absolutewrite.com^*/48HrBooks4.jpg ||absolutewrite.com^*/doyle_editorial.jpg ||absolutewrite.com^*/Scrivener-11-thumbnail-cover_160x136.gif ||absolutewrite.com^*_468x60banner. ||absolutewrite.com^*_ad.jpg ||ac2.msn.com^ ||access.njherald.com^ ||accesshollywood.com/aife?$subdocument ||acidcow.com/banners.php? ||acs86.com/a.htm? ||activewin.com/images/*_ad.gif ||activewin.com^*/blaze_static2.gif ||actressarchives.com/takeover/ ||ad.cooks.com^ ||ad.digitimes.com.tw^ ||ad.directmirror.com^ ||ad.download.cnet.com^ ||ad.evozi.com^ ||ad.fnnews.com^ ||ad.jamster.com^ ||ad.lyricswire.com^ ||ad.mangareader.net^ ||ad.newegg.com^ ||ad.pandora.tv^ ||ad.reachlocal.com^ ||ad.search.ch^ ||ad.services.distractify.com^ ||adamvstheman.com/wp-content/uploads/*/AVTM_banner.jpg ||adcitrus.com^ ||addirector.vindicosuite.com^ ||adds.weatherology.com^ ||adelaidecityfc.com.au/oak.swf ||adf.ly/external/*/int.php ||adf.ly/networks/ ||adifferentleague.co.uk^*/mcad.png ||adirondackmtnclub.com/images/banner/ ||adlink.shopsafe.co.nz^ ||admeta.vo.llnwd.net^ ||adpaths.com/_aspx/cpcinclude.aspx? ||adpost.com/bannerserver.g. ||adpost.com/rectserver.g. ||adpost.com/skyserver.g. ||adpost.com^*.g.html ||ads-*.hulu.com^ ||ads-rolandgarros.com^ ||ads.pof.com^ ||ads.zynga.com^ ||adsatt.abcnews.starwave.com^ ||adsatt.espn.starwave.com^ ||adshare.freedocast.com^ ||adsor.openrunner.com^ ||adss.yahoo.com^ ||adstil.indiatimes.com^ ||adtest.theonion.com^ ||adv.li/ads/ ||advanced-television.com^*/banners/ ||advertise.twitpic.com^ ||adverts.itv.com^$image ||advfn.com/tf_ ||advpc.net/site_img/banner/ ||adx.kat.ph^ ||adz.lk^*_ad. ||aetv.com/includes/dart/ ||aff.lmgtfy.com^ ||affiliatesynergy.com^*/banner_ ||afloat.ie^*/banners/ ||afmradio.co.za/images/slider/ ||africanbusinessmagazine.com/images/banners/ ||africaonline.com.na^*/banners/ ||afternoondc.in/banners/ ||agriculturalreviewonline.com/images/banners/ ||ahashare.com/cpxt_ ||ahk-usa.com/uploads/tx_bannermanagement/ ||ajnad.aljazeera.net^ ||akamai.net/*/Prerolls/Campaigns/ ||akamaihd.net/zbar/takeovers/ ||akamaihd.net^*/ads/$domain=player.theplatform.com ||akiba-online.com/forum/images/bs.gif ||akiba.ookami-cdn.net/images/subby.jpg$domain=akiba-online.com ||akinator.com/publicite_ ||akipress.com/_ban/ ||akipress.org/ban/ ||akipress.org/bimages/ ||alachuacountytoday.com/images/banners/ ||alarabiya.net/dms/takeover/ ||alaska-native-news.com/files/banners/ ||alatest.co.uk/banner/ ||alatest.com/banner/ ||all4divx.com/js/jscode2.js ||allghananews.com/images/banners/ ||allhiphop.com/site_resources/ui-images/*-conduit-banner.gif ||allkpop.com^*/takeover/ ||allmovieportal.com/dynbanner. ||allmyvideos.net/js/ad_ ||allmyvideos.net/player/ova-jw.swf ||allmyvideos.net^*/pu.js ||allthelyrics.com^*/popup.js ||allthingsd.com^*/sponsor- ||allthingsd.com^*_ad_ ||altdaily.com/images/banners/ ||alternet.org/givememygfp. ||amazingmoneymagnet.com//upload/banners/ ||amazon.com/aan/$subdocument ||amazonaws.com/cdn.megacpm.com/ ||amazonaws.com/cdn/campaign/$domain=caclubindia.com ||amazonaws.com/cdn/ipfc/$object,domain=caclubindia.com ||amazonaws.com/files.bannersnack.com/ ||amazonaws.com/videos/$domain=technewstoday.com ||amazonaws.com^*-ad.jpg$domain=ewn.co.za ||amazonaws.com^*-Banner.jpg$domain=ewn.co.za ||amazonaws.com^*/site-takeover/$domain=songza.com ||amazonaws.com^*MPU%20Banner.jpg$domain=ewn.co.za ||ambriefonline.com^*/banners/ ||amd.com/publishingimages/*/master_ ||americanangler.com/images/banners/ ||americanfreepress.net/assets/images/Banner_ ||amnesty.ca/images/banners/ ||amz.steamprices.com^ ||analytics.mmosite.com^ ||anamera.com/DesktopModules/BannerDisplay/ ||anchorfree.com/delivery/ ||anchorfree.net/?tm=$subdocument ||anchorfree.net^*/?tm=$subdocument ||andr.net/banners/ ||androidcommunity.com/external_marketing/$subdocument ||androidpolice.com/wp-content/*/images/das/ ||anhits.com/files/banners/ ||anilinkz.com/img/leftsponsors. ||anilinkz.com/img/rightsponsors ||anilinkz.tv/kwarta- ||animationxpress.com/anex/crosspromotions/ ||animationxpress.com/anex/solutions/ ||anime-source.com/banzai/banner.$subdocument ||anime1.com/service/joyfun/ ||anime44.com/anime44box.jpg ||anime44.com/images/videobb2.png ||animea.net/do/ ||animeflavor.com/animeflavor-gao-gamebox.swf ||animeflv.net/cpm.html ||animefushigi.com/boxes/ ||animehaven.org/wp-content/banners/ ||animenewsnetwork.com/stylesheets/*skin$image ||animenewsnetwork.com^*.aframe? ||animeshippuuden.com/adcpm.js ||animeshippuuden.com/square.php ||aniscartujo.com^*/layer.js ||annistonstar.com/leaderboard_banner ||anonib.com/zimages/ ||anonytext.tk/img/paste-eb.png ||anonytext.tk/img/paste-sponsor.png ||anonytext.tk/re.php ||answerology.com/index.aspx?*=ads.ascx ||antag.co.uk/js/ov.js.php? ||anti-leech.com/al.php? ||anti-scam.org/abanners/ ||anvisoft.com^*/anviad.jpg ||aol.co.uk/images/skybet-logo.gif ||aolcdn.com/os/movies/css-js/sprite/*-wallpaper?$domain=moviefone.com ||apa.az^*/rebans/ ||apanews.net/pub/ ||apcointl.org/images/corporate_partners/ ||api.toptenreviews.com^*/request.php ||appleinsider.com/macmall ||appleinsider.com^*/ai_front_page_google_premium.js ||appleserialnumberinfo.com/desktop/sdas/$subdocument ||applifier.com/bar.htm? ||appspot.com/adop/ ||appwork.org/a_d_s/ ||aps.dz^*/banners/ ||ar15.com/biz/ ||ar15.com/images/highlight/ ||ar15.com^*_60x180.jpg ||aravot.am/banner/ ||archeagedatabase.net/images/okaygoods.gif ||arenabg.com^*/banners/ ||arenadb.net^*/banners/ ||armorgames.com/assets/*_skin_ ||armorgames.com^*/banners/ ||armorgames.com^*/site-skins/ ||armorgames.com^*/siteskin.css ||armslist.com/images/sponsors/ ||armyrecognition.com^*/customer/ ||arnnet.com.au/files/skins/ ||aroundosceola.com/banner- ||arsenal-mania.com/images/backsplash_ ||arstechnica.net/public/shared/scripts/da- ||arstechnica.net^*/sponsor- ||artima.com/zcr/ ||as.inbox.com^ ||asianewsnet.net/banner/ ||ask.com/display.html? ||ask.com/fifdart? ||askandyaboutclothes.com/images/$~third-party ||askbobrankin.com/awpopup*.js ||astalavista.com/avtng/ ||astalavista.com^*/sponsor- ||astronomy.com/sitefiles/overlays/overlaygenerator.aspx? ||astronomynow.com/wp-content/promos/ ||atdhe.ws/pp.js ||atimes.com/banner/ ||atimes.com^*/ahm728x90.swf ||attitude.co.uk/images/Music_Ticket_Button_ ||atđhe.net/pu/ ||augusta.com/sites/*/yca_plugin/yahoo.js$domain=augusta.com ||auto123.com/sasserve.spy ||autoline-eu.co.uk/atlads/ ||autoline-eu.co.za/atlads/ ||autoline-eu.ie/atlads/ ||autoline.info/atlads/ ||autosport.com/skinning/ ||autoworld.co.za^*/ads/ ||avaxnews.net/yb_$subdocument,domain=avaxhm.com ||aveherald.com/images/banners/ ||avforums.com/images/skins/ ||aviationweek.com^*/leader_board.htm ||avitop.com/image/amazon/ ||avitop.com/image/mig-anim.gif ||avitop.com/image/mig.gif ||avn.com/delivery/ ||avpa.dzone.com^ ||avsforum.com/alliance/ ||avstop.com/avbanner/ ||awkwardfamilyphotos.com*/?ad= ||azcentral.com/incs/dfp-refresh.php.inc? ||azcs.co.uk^*/backgrounds/rotate.php ||azlyrics.com^*_az.js ||b.localpages.com^ ||b.thefile.me^ ||b92.net/images/banners/ ||ba.ccm2.net^ ||ba.kioskea.net^ ||babelzilla.org/forum/images/powerfox-top.png ||babelzilla.org/images/banners/babelzilla-powerfox.png ||babycenter.com/viewadvertorialpoll.htm ||backin.net/s/promo/ ||backpagelead.com.au/images/banners/ ||badongo.com^*_banner_ ||bahamaslocal.com/img/banners/ ||baixartv.com/img/bonsdescontos. ||bakercountypress.com/images/banners/ ||ballerarcade.com/ispark/ ||ballislife.com^*/ova-player.swf$object-subrequest ||ballz.co.za/system-files/banners/ ||ballz.co.za^*/CLIENTS/ ||banner.automotiveworld.com^ ||banner.itweb.co.za^ ||banners.beevpn.com^ ||banners.beted.com^ ||banners.clubworldgroup.com^ ||banners.expressindia.com^ ||banners.friday-ad.co.uk/hpbanneruploads/$image ||banners.i-comers.com^ ||banners.itweb.co.za^ ||banners.playocio.com^ ||barnesandnoble.com/promo/ ||baseballamerica.com/plugs/ ||bashandslash.com/images/banners/ ||basinsradio.com/images/banners/ ||bassmaster.com^*/premier_sponsor_logo/ ||bay.com.mt/images/banners/ ||bay.com.mt/modules/mod_novarp/ ||bayfiles.net/img/download-button-orange.png ||baymirror.com/static/img/bar.gif ||baymirror.com/static/js/4728ba74bc.js ||bazaraki.com/bannerImage.php? ||bbc.co.uk^*/bbccom.js? ||bbc.com^*/logoDupontSmall.png ||bcdb.com^*/banners.pl? ||bdnews24.com^*/Ads/ ||beap.gemini.yahoo.com^ ||beforeitsnews.com/static/data/story-stripmall-new.html ||beforeitsnews.com/static/iframe/ ||beingpc.com^*/banners/ ||belfasttelegraph.co.uk/editorial/web/survey/recruit-div-img.js ||bellanaija.com^*/wp-banners/ ||bellevision.com/belle/adds/ ||benchmarkreviews.com^*/banners/ ||bernama.com/banner/ ||bestblackhatforum.com/images/my_compas/ ||bestlistonline.info/link/ad.js ||bestvpn.com/wp-content/uploads/*/mosttrustedname_260x300_ ||bets4free.co.uk/content/5481b452d9ce40.09507031.jpg ||bettingsports.com/top_bonuses ||bettingsports.com/where_to_bet ||bettyconfidential.com/media/fmads/ ||beyondd.co.nz/ezibuy/$third-party,domain=stuff.co.nz ||bigeddieradio.com/uploads/sponsors/ ||bigpoint.com/xml/recommender.swf? ||bigsports.tv/live/ado.php ||bikeforums.net/images/sponsors/ ||bikeradar.com/media/img/commercial/ ||bing.com/fblogout?$subdocument,domain=facebook.com ||binsearch.info/iframe.php ||bips.channel4.com^*/backgrounds/$image,domain=channel4.com ||bit-tech.net/images/backgrounds/skin/ ||bitcoinist.net/wp-content/*/630x80-bitcoinist.gif ||bitcoinist.net/wp-content/uploads/*_250x250_ ||bitcoinreviewer.com/wp-content/uploads/*/banner-luckybit.jpg ||bitminter.com/images/info/spondoolies ||bitreactor.to/sponsor/ ||bitreactor.to/static/subpage$subdocument ||bittorrent.am/banners/ ||bizarremag.com/images/skin_ ||bizhub.vn^*/agoda-for-bizhub.jpg ||bkmag.com/binary/*/1380x800_ ||blackberryforums.net/banners/ ||blackchronicle.com/images/Banners- ||blackhatlibrary.net/hacktalk.png ||blacklistednews.com/images/*banner ||blackpressusa.com^*/Ford.jpg ||blackpressusa.com^*250by300. ||blackpressusa.com^*300by250. ||blackpressusa.com^*300x250. ||blasternation.com/images/hearthstone.jpg ||blbclassic.org/assets/images/*banners/ ||bleacherreport.net/images/skins/ ||bleacherreport.net^*_redesign_skin_ ||blinkx.com/adhocnetwork/ ||blip.fm/ad/ ||blitzdownloads.com/promo/ ||blog.co.uk/script/blogs/afc.js ||blogevaluation.com/templates/userfiles/banners/ ||blogorama.com/images/banners/ ||blogsdna.com/wp-content/themes/blogsdna2011/images/advertisments.png ||blogsmithmedia.com^*_skin. ||blogsmithmedia.com^*_skin_ ||blogsmithmedia.com^*wallpaper$image,domain=joystiq.com ||blogspider.net/images/promo/ ||bloomberg.com^*/banner.js ||bn0.com/4v4.js ||bnrs.ilm.ee^ ||bolandrugby.com/images/sponsors. ||bom.gov.au/includes/marketing2.php? ||bookingbuddy.com/js/bookingbuddy.strings.php?$domain=smartertravel.com ||botswanaguardian.co.bw/images/banners/ ||boulderjewishnews.org^*/JFSatHome-3.gif ||boxlotto.com/banrotate. ||bp.blogspot.com^*%2bad*.jpg$domain=lindaikeji.blogspot.com ||bp.blogspot.com^*/poster*.jpg$domain=lindaikeji.blogspot.com ||bp.blogspot.com^*banner*.jpg$domain=lindaikeji.blogspot.com ||brandchannel.com/images/educationconference/ ||break.com^*/marketguide- ||brecorder.com^*/banners/ ||breitlingsource.com/images/govberg*.jpg ||breitlingsource.com/images/pflogo.jpg ||brenz.net/img/bannerrss.gif ||brightcove.com/js/BrightcoveExperiences.js$domain=java-forums.org ||britishcolumbia.com/sys/ban.asp ||broadbandchoices.co.uk/aff.js ||broadbandforum.co/stock/ ||broadbandgenie.co.uk/images/takeover/ ||broadbandgenie.co.uk/img/talktalk/$image ||broadcastify.com/sm/ ||broadcastingworld.net/*-promo.jpg ||broadcastingworld.net/marquee- ||brobible.com/files/uploads/images/takeovers/ ||brothersoft.com/gg/center_gg.js ||brothersoft.com/gg/g.js ||brothersoft.com/gg/kontera_com.js ||brothersoft.com/gg/soft_down.js ||brothersoft.com/gg/top.js ||brothersoft.com/softsale/ ||brothersoft.com^*/float.js ||brothersoft.com^*/homepage_ppd.html ||brothersoft.com^*/softsale/ ||brownfieldonline.com^*/banners/ ||browsershots.org/static/images/creative/ ||brudirect.com/images/banners/ ||bsmphilly.com/files/banners/ ||bsvc.ebuddy.com/bannerservice/tabsaww ||bt-chat.com/images/affiliates/ ||bt.am/banners/ ||btdigg.org/images/btguard ||btkitty.com/static/images/880X60.gif ||btkitty.org/static/images/880X60.gif ||btmon.com/da/$subdocument ||bundesliga.com^*/_partner/ ||busiweek.com^*/banners/ ||buy-n-shoot.com/images/banners/banner- ||buy.com/*/textlinks.aspx ||buyselltrade.ca/banners/ ||buzzintown.com/show_bnr.php? ||buzznet.com/topscript.js.php? ||bvibeacon.com^*/banners/ ||bwp.theinsider.com.com^ ||bypassoxy.com/vectrotunnel-banner.gif ||c-sharpcorner.com^*/banners/ ||c-ville.com/image/pool/ ||c21media.net/wp-content/plugins/sam-images/ ||c9tk.com/images/banner/ ||cadplace.co.uk/banner/ ||cadvv.heraldm.com^ ||cadvv.koreaherald.com^ ||cafemomstatic.com/images/background/$image ||cafimg.com/images/other/ ||cafonline.com^*/sponsors/ ||caladvocate.com/images/banner- ||caledonianrecord.com/iFrame_ ||caledonianrecord.com/SiteImages/HomePageTiles/ ||caledonianrecord.com/SiteImages/Tile/ ||calgaryherald.com/images/sponsor/ ||calgaryherald.com/images/storysponsor/ ||canalboat.co.uk^*/bannerImage. ||canalboat.co.uk^*/Banners/ ||cananewsonline.com/files/banners/ ||cancomuk.com/campaigns/ ||candystand.com/game-track.do? ||canindia.com^*_banner.png ||capitalethiopia.com/images/banners/ ||capitalfm.co.ke^*/830x460-iv.jpg ||capitolfax.com/wp-content/*ad. ||capitolfax.com/wp-content/*Ad_ ||captchaad.com/captchaad.js$domain=gca.sh ||card-sharing.net/cccamcorner.gif ||card-sharing.net/topsharingserver.jpg ||card-sharing.net/umbrella.png ||cardomain.com/empty_pg.htm ||cardschat.com/pkimg/banners/ ||cardsharing.info/wp-content/uploads/*/ALLS.jpg ||cargonewsasia.com/promotion/ ||cars.com/go/includes/targeting/ ||cars.com/js/cars/catretargeting.js ||carsales.com.au^*/backgrounds/ ||carsguide.com.au/images/uploads/*_bg. ||carsguide.com.au^*/marketing/ ||carsuk.net/directory/panel-promo- ||cash9.org/assets/img/banner2.gif ||castanet.net/clients/ ||casualgaming.biz/banners/ ||catalystmagazine.net/images/banners/ ||catholicculture.org/images/banners/ ||cbc.ca/deals/ ||cbc.ca/video/bigbox.html ||cbfsms.com^*-banner.gif ||cbn.co.za/images/banners/ ||cbsinteractive.co.uk/cbsi/ads/ ||cbslocal.com/deals/widget/ ||cbslocal.com/rotatable? ||ccfm.org.za^*/sads/ ||cd1025.com/www/assets/a/ ||cd1025.com/www/img/btn- ||cdcovers.cc/images/external/toolbar ||cdmagurus.com/forum/cyberflashing.swf ||cdmagurus.com/img/*.gif ||cdmagurus.com/img/kcpf2.swf ||cdmediaworld.com*/! ||cdn-surfline.com/home/billabong-xxl.png ||cdn.turner.com^*/groupon/ ||ceforum.co.uk/images/misc/PartnerLinks ||celebjihad.com/widget/widget.js$domain=popbytes.com ||centos.org/donors/ ||centralfm.co.uk/images/banners/ ||ceoexpress.com/inc/ads ||ceylontoday.lk^*/banner/ ||cghub.com/files/CampaignCode/ ||ch131.so/images/2etio.gif ||chaklyrics.com/add$subdocument ||channel4.com/assets/programmes/images/originals/$image ||channel4.com/bips/*/brand/$image ||channel4fm.com/images/background/ ||channel4fm.com/promotion/ ||channel5.com/assets/takeovers/ ||channelonline.tv/channelonline_advantage/ ||chapala.com/wwwboard/webboardtop.htm ||checkpagerank.net/banners/ ||checkwebsiteprice.com/images/bitcoin.jpg ||chelsey.co.nz/uploads/Takeovers/ ||chicagodefender.com/images/banners/ ||chinanews.com/gg/ ||chronicle.lu/images/banners/ ||chronicle.lu/images/Sponsor_ ||churchnewssite.com^*-banner1. ||churchnewssite.com^*/banner- ||churchnewssite.com^*/bannercard- ||ciao.co.uk/load_file.php? ||ciao.com^*/price_link/ ||cinemablend.com/templates/tpl/reskin/$image ||cineplex.com/skins/ ||ciol.com/zedotags/ ||citeulike.org/static/campaigns/ ||citizen-usa.com/images/banners/ ||cityam.com^*/pageskin/ ||citybeat.co.uk^*/ads/ ||citywire.co.uk/wealth-manager/marketingcampaign? ||citywirecontent.co.uk^*/cw.oas.dx.js ||clarksvilleonline.com/cols/ ||classic-tv.com/burst$subdocument ||classic-tv.com/pubaccess.html ||classic97.net^*/banner/ ||classical897.org/common/sponsors/ ||classicfeel.co.za^*/banners/ ||classicsdujour.com/artistbanners/ ||clgaming.net/interface/img/sponsor/ ||click.livedoor.com^ ||clicks.superpages.com^ ||cloudfront.net/*/takeover/$domain=offers.com ||cloudfront.net/ccmtblv2.png$domain=aim.org ||cloudfront.net/hot/ars.dart/$domain=arstechnica.com ||clubhyper.com/images/hannantsbanner_ ||clubplanet.com^*/wallpaper/ ||cmodmedia*.live.streamtheworld.com/media/cm-audio/cm:*.mp3$domain=rdio.com ||cmpnet.com/ads/ ||cms.myspacecdn.com^*/splash_assets/ ||cnet.com/imp? ||cnettv.com.edgesuite.net^*/ads/ ||cnetwidget.creativemark.co.uk^ ||cnn.com/ad- ||cnn.com/cnn_adspaces/ ||cnn.com^*/ad_policy.xml$object-subrequest,domain=cnn.com ||cnn.com^*/banner.html?&csiid= ||cnn.net^*/lawyers.com/ ||cntv.cn/Library/js/js_ad_gb.js ||cnx-software.com/pic/gateworks/ ||cnx-software.com/pic/technexion/ ||coastfm.ae/images/background/ ||coastfm.ae/promotion/ ||coastweek.com/banner_ ||coastweek.com/graffix/ ||cocomment.com/banner? ||codeasily.com^*/codeasily.js ||codecguide.com/beforedl2.gif ||codecguide.com/driverscan2.gif ||codecguide.com/driverscantop1.gif ||coderanch.com/shingles/ ||coinad.com/op.php? ||coinurl.com/bootstrap/js/bootstrapx-clickover.js ||coinurl.com/bottom.php ||coinurl.com/get.php? ||coinurl.com/nbottom.php? ||collarme.com/anv/ ||collarme.com/zone_alt.asp ||collector.viki.io^ ||com-a.in/images/banners/ ||com.com/cnwk.1d/aud/ ||comicbookresources.com/assets/images/skins/ ||comicgenesis.com/tcontent.php?out= ||comparestoreprices.co.uk/images/promotions/ ||compassnewspaper.com/images/banners/ ||complaintsboard.com/img/202x202.gif ||complaintsboard.com/img/banner- ||complexmedianetwork.com^*/takeovers/ ||complexmedianetwork.com^*/toolbarlogo.png ||computerandvideogames.com^*/promos/ ||computerhelp.com/temp/banners/ ||computerworld.com^*/jobroll/ ||con-telegraph.ie/images/banners/ ||concrete.tv/images/banners/ ||connectionstrings.com/csas/public/a.ashx? ||conscioustalk.net/images/sponsors/ ||conservativetribune.com/cdn-cgi/pe/bag2?r[]=*revcontent.com ||console-spot.com^*.swf ||constructionreviewonline.com^*730x90 ||constructionreviewonline.com^*banner ||consumerreports.org^*/sx.js ||convertmyimage.com/images/banner-square.png ||conwaydailysun.com/images/banners/ ||conwaydailysun.com/images/Tiles_Skyscrapers/ ||coolfm.us/lagos969/images/banners/ ||coolmath-games.com/images/160-notice.gif ||coolmath.net/*-medrect.html ||coolsport.tv/adtadd. ||coolsport.tv/lshadd. ||copblock.org/wp-content/uploads/*/covert-handcuff-key-AD- ||cops.com^*/copbanner_ ||coryarcangel.com/images/banners/ ||cosplay.com/1lensvillage.gif ||countrychannel.tv/telvos_banners/ ||cphpost.dk^*/banners/ ||cpub.co.uk/a? ||crackdb.cd/cd.swf ||crackdb.com/img/vpn.png ||cramdodge.com/mg- ||craveonline.com/gnads/ ||crazy-torrent.com/web/banner/0xxx0.net.jpg ||crazy-torrent.com/web/banner/online.jpg ||crazymotion.net/video_*.php?key= ||creatives.livejasmin.com^ ||creattor.net/flashxmlbanners/ ||crimeaware.co.za/files-upload/banner/ ||crunchyroll.*/vast? ||crushorflush.com/html/promoframe.html ||cruzine.com^*/banners/ ||cryptocoinsnews.com/wp-content/uploads/*/ccn.png ||cryptocoinsnews.com/wp-content/uploads/*/cloudbet_ ||cryptocoinsnews.com/wp-content/uploads/*/xbt-social.png ||cryptocoinsnews.com/wp-content/uploads/*/xbt.jpg ||cryptocoinsnews.com/wp-content/uploads/*takeover ||crystalmedianetworks.com^*-180x150.jpg ||cship.org/w/skins/monobook/uns.gif ||ctmirror.org/randomsupporter/ ||ctv.ca/ctvresources/js/ctvad.js ||ctv.ca/Sites/Ctv/assets/js/ctvDfpAd.js ||cur.lv/bootstrap/js/bootstrapx-clickover.js ||cur.lv/nbottom.php? ||cyanogenmod.com/static/tdr_skyscraper.png ||cybergamer.com/skins/ ||d-addicts.com^*/banner/ ||d-h.st/assets/img/download1.png ||d.annarbor.com^ ||d.businessinsider.com^ ||d.gossipcenter.com^ ||d.imwx.com/js/wx-a21-plugthis- ||d.thelocal.com^ ||d5e.info/1.gif ||d5e.info/2.png ||d6vwe9xdz9i45.cloudfront.net/psa.js$domain=sporcle.com ||da.feedsportal.com^$~subdocument ||dabs.com/images/page-backgrounds/ ||dads.new.digg.com^ ||daily-mail.co.zm/images/banners/ ||daily-mail.co.zm/images/stories/sbt.gif ||dailybitcoins.org/banners/ ||dailyblogtips.com/wp-content/uploads/*.gif ||dailycommercial.com/inc.php? ||dailydeal.news-record.com/widgets/ ||dailydeals.amarillo.com^ ||dailydeals.augustachronicle.com^ ||dailydeals.brainerddispatch.com^ ||dailydeals.lubbockonline.com^ ||dailydeals.onlineathens.com^ ||dailydeals.savannahnow.com^ ||dailydeals.sfgate.com/widget/ ||dailyexpress.com.my/banners/ ||dailyexpress.com.my/image/banner/ ||dailyfreegames.com/js/partners.html ||dailyherald.com^*/contextual.js ||dailyhome.com/leaderboard_banner ||dailymail.co.uk/i/pix/*_107x58.jpg ||dailymail.co.uk/i/pix/*_308x164.jpg ||dailymail.co.uk/i/pix/*_308x262.jpg ||dailymail.co.uk/i/pix/ebay/ ||dailymail.co.uk/modules/commercial/ ||dailymail.co.uk^*/promoboxes/ ||dailymirror.lk/media/images/Nawaloka- ||dailymotion.com/images/ie.png ||dailymotion.com/skin/data/default/partner/$~stylesheet ||dailymotion.com^*masscast/ ||dailynews.co.tz/images/banners/ ||dailynews.co.zw^*-takeover. ||dailynews.gov.bw^*/banner_ ||dailynews.lk^*/webadz/ ||dailypioneer.com/images/banners/ ||dailypuppy.com/images/livestrong/ls_diet_120x90_1.gif ||dailysabah.com/banner/ ||dailytimes.com.pk/banners/ ||dailytrust.info/images/banners/ ||dailytrust.info/images/dangote.swf ||dailywritingtips.com^*/publisher2.gif ||damnlol.com/a/leaderboard.php ||damnlol.com/damnlol.com.*.js ||datpiff.com/skins/misc/ ||davesite.com^*/aff/ ||dayport.com/ads/ ||dbstalk.com/sponsors/ ||dcad.watersoul.com^ ||dcourier.com/SiteImages/Banner/ ||ddccdn.com/js/google_ ||ddl2.com/header.php? ||dealmedia.utsandiego.com^ ||deals.cultofmac.com^$subdocument ||deals.iphonehacks.com^$subdocument ||deals.ledgertranscript.com^ ||deborah-bickel.de/banners/ ||decadeforum.com/images/misc/download2.png ||deccanchronicle.com^*-banner- ||deccanchronicle.com^*-searchquad-300100.swf ||decryptedtech.com/images/banners/ ||defenceweb.co.za/images/sponsorlogos/ ||defenceweb.co.za/logos/ ||defensereview.com^*_banner_ ||delvenetworks.com^*/acudeo.swf$object-subrequest,~third-party ||demerarawaves.com/images/banners/ ||demonoid.unblockt.com/cached/$subdocument ||depic.me/bann/ ||depositphotos.com^$subdocument,third-party ||deseretnews.com/img/sponsors/ ||deshvidesh.com/banner/ ||desiretoinspire.net/storage/layout/modmaxbanner.gif ||desiretoinspire.net/storage/layout/royalcountessad.gif ||desiretoinspire.net^*/mgbanner.gif ||desiretoinspire.net^*125x125 ||desixpress.co.uk/image/banners/ ||detnews.com^*/sponsor/ ||detroitindependent.net/images/ad_ ||develop-online.net/static/banners/ ||devicemag.com^$subdocument,~third-party ||devour.com/*skin ||devshed.com/images/backgrounds/$image ||devtools2.networkcities.net/wp-content/uploads/output_trLIFi.gif$domain=smallseotools.com ||devx.com/devx/3174.gif ||dezeen.com/wp-content/themes/dezeen-aa-hpto-mini-sept-2014/ ||diamondworld.net/admin/getresource.aspx? ||dictionary.cambridge.org/info/frame.html?zone= ||dictionary.com^*/serp_to/ ||digdug.divxnetworks.com^ ||digitaljournal.com/promo/ ||digitalreality.co.nz^*/360_hacks_banner.gif ||digitizor.com/wp-content/digimages/xsoftspyse.png ||digzip.com^*baner.swf ||diplodocs.com/shopping/sol.js ||dippic.com/images/banner ||dishusa.net/templates/flero/images/book_sprava.gif ||dispatch.com^*/dpcpopunder.js ||display.superbay.net^ ||distrogeeks.com/images/sponsors/ ||distrowatch.com/images/kokoku/ ||distrowatch.com^*-*.gif ||distrowatch.com^*/3cx.png ||distrowatch.com^*/advanced-admin. ||dividendchannel.com/toprankedsm.gif ||divxme.com/images/play.png ||divxstage.eu/images/download.png ||diytrade.com/diyep/dir?page=common/ppadv& ||djluv.in/android.gif ||djmag.co.uk/sites/default/files/takeover/ ||djmag.com/sites/default/files/takeover/ ||djtunes.com^*/adbg/ ||dl-protect.com/pop.js ||dl4all.com/data4.files/dpopupwindow.js ||dl4all.com/img/download.jpg ||dl4all.com^*/hotfile.gif ||dmros.ysm.yahoo.com^ ||dnsstuff.com/dnsmedia/images/*_banner.jpg ||dnsstuff.com/dnsmedia/images/ft.banner. ||doge-dice.com/images/faucet.jpg ||doge-dice.com/images/outpost.png ||dogechain.info/content/img/a ||domainmarket.com/mm/ ||domaintools.com/eurodns_ ||domaintools.com/marketing/ ||domaintools.com/partners/ ||dominicantoday.com/stor/banners/ ||dontblockme.modaco.com^ ||dota-trade.com/img/branding_ ||doubleclick.net/gampad/ads?*^vpos^$domain=cbs.com ||doubleviking.com/ss.html ||downforeveryoneorjustme.com/images/dotbiz_banner.jpg ||downloadbox.to/Leadertop.html ||downloadian.com/assets/banner.jpg ||dprogram.net^*/rightsprites.png ||dpstatic.com/banner.png? ||dpstatic.com/s/ad.js ||dramabay.com/y/$subdocument ||dreamscene.org^*_Banner. ||drhinternet.net/mwimgsent/ ||drivearchive.co.uk/amazon/ ||drivearchive.co.uk/images/amazon. ||driverdb.com/campaigns/banners/ ||droidgamers.com/images/banners/ ||dsogaming.com/interstitial/ ||dubcnm.com/Adon/ ||duckduckgo.com/i.js?o=a& ||duckduckgo.com/m.js?*&o=a ||duckduckgo.com/y.js ||duckload.com/js/abp.php? ||dump8.com/tiz/ ||dump8.com/wget.php ||dump8.com/wget_2leep_bottom.php ||durbannews.co.za^*_new728x60.gif ||dustcoin.com^*/image/ad- ||dvdvideosoft.com^*/banners/ ||dwarfgames.com/pub/728_top. ||dyncdn.celebuzz.com/assets/ ||e90post.com/forums/images/banners/ ||earthlink.net^*/promos/ ||earthmoversmagazine.co.uk/nimg/ ||eastonline.eu/images/banners/ ||eastonline.eu/images/eng_banner_ ||easybytez.com/pop3.js ||eatsleepsport.com/images/manorgaming1.jpg ||ebayrtm.com/rtm?RtmCmd*&enc= ||ebayrtm.com/rtm?RtmIt ||ebaystatic.com/aw/pics/signin/*_signInSkin_ ||ebaystatic.com/aw/signin/*_wallpaper_$image ||ebizblitz.co.za/upload/ad/ ||ebizmbainc.netdna-cdn.com/images/tab_sponsors.gif ||ebookshare.net/pages/lt.html ||ebookshare.net^*/streamdirect160x600_ ||ebuddy.com/textlink.php? ||ebuddy.com/web_banners/ ||ebuddy.com/web_banners_ ||eclipse.org/membership/promo/images/ ||ecommerce-journal.com/specdata.php? ||economist.com.na^*/banners/ ||economist.com^*/timekeeper-by-rolex-medium.png ||ecostream.tv/assets/js/pu.min.js ||ecostream.tv/js/pu.js ||ed2k.2x4u.de/mfc/ ||edgedatg.com^*/AdCountdownPlugin.swf$object-subrequest,domain=abc.go.com ||edgedatg.com^*/FreeWheelDATGPlugin.swf$object-subrequest,domain=abc.go.com ||educationbusinessuk.net/images/stage.gif ||egamer.co.za^*-background- ||ehow.co.uk/frames/directas_ ||ehow.com/images/brands/ ||ehow.com/marketing/ ||ehow.com/media/ad.html^ ||ejb.com/300_250 ||ejpress.org/images/banners/ ||ejpress.org/img/banners/ ||ekantipur.com/uploads/banner/ ||electricenergyonline.com^*/bannieres/ ||electronicsfeed.com/bximg/ ||elevenmyanmar.com/images/banners/ ||elgg.org/images/hostupon_banner.gif ||elivetv.in/pop/ ||elocallink.tv^*/showgif.php? ||emergencymedicalparamedic.com/wp-content/uploads/2011/12/anatomy.gif ||emoneyspace.com/b.php ||empirestatenews.net/Banners/ ||emsservice.de.s3.amazonaws.com/videos/$domain=zattoo.com ||emsservice.de/videos/$domain=zattoo.com ||emule-top50.com/extras/$subdocument ||emuleday.com/cpxt_$subdocument ||encyclopediadramatica.es/edf/$domain=~forum.encyclopediadramatica.es ||encyclopediadramatica.es/lanhell.js ||encyclopediadramatica.es/spon/ ||encyclopediadramatica.se/edf/$domain=~forum.encyclopediadramatica.se ||energytribune.com/res/banner/ ||england.fm/i/ducksunited120x60english.gif ||englishtips.org/b/ ||enigmagroup.org/clients/privatetunnels.swf ||environmental-finance.com^*banner ||environmental-finance.com^*rotate.gif ||epicshare.net/p1.js ||epictv.com/sites/default/files/290x400_ ||episodic.com^*/logos/player- ||eprop.co.za/images/banners/ ||eq2flames.com/images/styles/eq2/images/banner ||espn.co.uk/espnuk/williamhill/ ||espn.co.uk/espnuk/williamhill_ ||espn.co.uk^*/viagogo_sports.html ||espn.go.com/ads/ ||espn.vad.go.com^$domain=youtube.com ||espn1320.net/get_preroll.php? ||essayinfo.com/img/125x125_ ||essayscam.org^*/ads.js ||esus.com/images/regiochat_logo.png ||eteknix.com/wp-content/uploads/*skin ||eteknix.com/wp-content/uploads/*Takeover ||etidbits.com/300x250news.php ||euphonik.dj/img/sponsors- ||eurochannel.com/images/banners/ ||eurocupbasketball.com^*/sponsors- ||eurodict.com/images/banner_ ||eurogamer.net/quad.php ||eurogamer.net^*/takeovers/ ||euroleague.net^*/sponsors- ||euronews.com/media/farnborough/farnborough_wp.jpg ||european-rubber-journal.com/160x600px_ ||europeonline-magazine.eu/banner/ ||europeonline-magazine.eu/nuroa/ ||euroweb.com^*/banner/ ||eva.ucas.com^ ||eve-search.com/gge.gif ||eveningecho.ie/cdn-cgi/pe/bag?r[]=*pubads.g.doubleclick.net ||eventful.com/tools/click/url? ||evernote.com/prom/img/ ||everythingsysadmin.com^*_sw_banner120x600_ ||evolutionm.net/SponsorLogos/ ||evony.com/sevonyadvs2. ||eweek.com/images/stories/marketing/ ||eweek.com/widgets/ibmtco/ ||eweek.com^*/sponsored- ||ewrc-results.com/images/horni_ewrc_result_banner3.jpg ||ex1.gamecopyworld.com^$subdocument ||exashare.com/player_file.jpg ||exceluser.com^*/pub/rotate_ ||exchangerates.org.uk/images-NEW/tor.gif ||exchangerates.org.uk/images/150_60_ ||exchangerates.org.uk/images/200x200_ ||excite.com/gca_iframe.html ||expatexchange.com/banner/ ||expatwomen.com/expat-women-sponsors/ ||expertreviews.co.uk/?act=widgets. ||expertreviews.co.uk^*/skins/ ||express.co.uk^*/sponsored/ ||expressmilwaukee.com/engines/backgrounds/js/backgrounds.js ||expreview.com/exp2/ ||extratorrent.cc/images/wintoolspro.gif ||extratorrent.cc/scripts/bo1o.js ||extratorrent.cc/scripts/pp_ ||extremeoverclocking.com/template_images/it120x240.gif ||ezmoviestv.com^*/ad-for-ezmovies.png ||faadooengineers.com/ads/ ||facenfacts.com^*/ads/ ||fakku.net/static/seele-$subdocument ||fallout3nexus.com^*/300x600.php ||familylawweek.co.uk/bin_1/ ||famouspornstarstube.com/images/sponsors/ ||fan.twitch.tv^ ||fancystreems.com/300x2503.php ||fanfusion.org/as.js ||fansshare.com/va/?$subdocument ||fark.com/cgi/buzzfeed_link.pl ||farmville.com/promo_bar.php ||fastcompany.com/sites/*/interstitial.js ||fastvideo.eu/images/down.png ||fastvideo.eu/images/pl_box_rapid.jpg ||fbcdn.net^*/flyers/$domain=facebook.com ||feed-the-beast.com^*/gamevox.png ||feedly.com/amazon.$xmlhttprequest ||feeds.feedburner.com/*.gif ||feedsportal.com/creative/ ||feedsportal.com/videoserve/ ||feiwei.tv^*/sandbox.html ||fff.dailymail.co.uk^ ||ffiles.com/counters.js ||fgfx.co.uk/banner.js? ||fhm.com/images/casinobutton.gif ||fhm.com/images/sportsbutton.gif ||fhm.com^*_background.jpg ||fhm.com^*_banner.png ||fiberupload.org/300en.png ||fightersonlymag.com/images/banners/ ||fijitimes.com/images/bspxchange.gif ||file.org/fo/scripts/download_helpopt.js ||file.org^*/images/promo/ ||file2hd.com/sweet.jpg ||filedino.com/imagesn/downloadgif.gif ||fileflyer.com/img/dap_banner_ ||filegaga.com/ot/fast.php? ||fileom.com/img/downloadnow.png ||fileom.com/img/instadownload2.png ||fileplanet.com/fileblog/sub-no-ad.shtml ||filerio.in^*/jquery.interstitial. ||files.wordpress.com/*-reskin. ||filesharingtalk.com/fst/8242/ ||fileshut.com/etc/links.php?q= ||filespart.com/ot/fast.aspx? ||filespazz.com/imx/template_r2_c3.jpg ||filespazz.com^*/copyartwork_side_banner.gif ||filipinojournal.com/images/banners/ ||filmovizija.com/Images/ludovanjeaffilate.jpg ||filmovizija.com/Images/photo4sell.jpg ||filmsite.org/dart-zones.js ||fimserve.ign.com^ ||financialnewsandtalk.com/scripts/slideshow-sponsors.js ||financialsamurai.com/wp-content/uploads/*/sliced-alternative-10000.jpg ||findfiles.com/images/icatchallfree.png ||findfiles.com/images/knife-dancing-1.gif ||findfreegraphics.com/underp.js ||findicons.com^*/125x125/ ||findit.com.mt/dynimage/boxbanner/ ||findit.com.mt/viewer/ ||findnsave.idahostatesman.com^ ||findthebest-sw.com/sponsor_event? ||finextra.com^*/leaderboards/ ||finextra.com^*/pantiles/ ||firedrive.com/appdata/ ||firedrive.com/appresources/ ||firingsquad.com^*/sponsor_row.gif ||firstnationsvoice.com/images/weblinks.swf ||firstpost.com/promo/ ||firstpost.com^*/sponsered- ||firstpost.com^*_skin_ ||firstpost.com^*_sponsored. ||firstpost.in^*/promo/ ||firstrows.biz/js/bn.js ||firstrows.biz/js/pu.js ||firstrowsports.li/frame/ ||firstrowusa.eu/js/bn.js ||firstrowusa.eu/js/pu.js ||firsttoknow.com^*/page-criteo- ||fishchannel.com/images/sponsors/ ||fiverr.com/javascripts/conversion.js ||flameload.com/onvertise. ||flashscore.com/res/image/bookmaker-list.png ||flashtv.co/adds/ ||flashtv.co/class/adjsxxs.js ||flashx.tv/nuevo/player/js/anya.js ||flashx.tv^*/counterck.html ||flashy8.com/banner/ ||flatpanelshd.com/pictures/*banner ||fleetwatch.co.za/images/banners/ ||flicks.co.nz/images/takeovers/ ||flicks.co.nz/takeovercss/ ||flightradar24.com/_includes/sections/airportAd.php ||flopturnriver.com*/banners/ ||flv.sales.cbs.com^$object-subrequest,domain=cbs.com|cbsnews.com|twitch.tv ||flyordie.com/games/free/b/ ||flyordie.com/games/online/ca.html ||fmr.co.za^*/banners/ ||fncstatic.com^*/sponsored-by.gif ||foodingredientsfirst.com/content/banners/ ||foodingredientsfirst.com/content/flash_loaders/loadlargetile.swf ||foodingredientsfirst.com/content/flash_loaders/loadskyscraper.swf ||football-italia.net/imgs/moveyourmouse.gif ||footballshirtculture.com/images/e12b.jpg ||footballtradedirectory.com^*banner ||fordforums.com.au/logos/ ||foreignersinuk.co.uk^*/banner/ ||forexpeacearmy.com/images/banners/ ||forumimg.ipmart.com/swf/ipmart_forum/banner ||forumw.org/images/uploading.gif ||forward.com/workspace/assets/newimages/amazon.png ||foxbusiness.com/html/google_homepage_promo ||foxsoccer2go.com/namedImage/*/backgroundSkin.jpg ||foxsports.com.au^*/sponsor/ ||foxsports.com/component/*_wallpaper_$image ||foxsports.com/component/xml/SBMarketingTakeOverPromos ||foxsports.com^*-Skin- ||foxsports.com^*-skin_ ||foxsports.com^*/Sponsors/ ||foxsports.com^*_skin_ ||foxsports540.com/images/banner1.png ||foxsports540.com/images/banner2.png ||foxsportsradio.com/pages/second300x250iframe.html ||fpscheats.com/banner-img.jpg ||fpscheats.com/fpsbanner.jpg ||freakshare.com/yild.js ||fredmiranda.com/buzz/canondble-600x90.jpg ||free-times.com/image/pool/ ||free-torrents.org^*/banners/ ||free-tv-video-online.me/300s.html ||free-tv-video-online.me/episode-buttom- ||free-tv-video-online.me/season-side- ||free-webhosts.com/images/a/ ||freeads.co.uk/ctx.php? ||freeappaday.com/nimgs/bb/ ||freemediatv.com/images/inmemoryofmichael.jpg ||freeminecraft.me/mw3.png ||freenode.net/images/ack_privateinternetaccess-freenode.png ||freenode.net/images/freenode_osuosl.png ||freepornsubmits.com/ads/ ||freeroms.com/bigbox.html ||freesoftwaremagazine.com/extras/ ||freestockcharts.com/symbolhit.aspx$subdocument ||freetv-video.ca^*/popover-load-js.php? ||freetypinggame.net/burst720.asp ||freevermontradio.org/pictures/lauren_Stagnitti.jpg ||freeworldgroup.com/banner ||frenchradiolondon.com/data/carousel/ ||fresh-weather.com/popup1.gif ||freshplaza.com/b/ ||freshremix.org/templates/freshremix_eng/images/300.gif ||freshremix.ru/images/ffdownloader1.jpg ||friday-ad.co.uk/banner.js? ||friday-ad.co.uk/endeca/afccontainer.aspx ||frombar.com/ads/ ||frozen-roms.in/popup.php ||frozen-roms.me/popup.php ||fscheetahs.co.za/images/Sponsers/ ||ftdworld.net/images/banners/ ||ftlauderdalewebcam.com/images/*webcambanner ||ftlauderdalewebcam.com^*-WebCamBannerFall_ ||fudzilla.com^*/banners/ ||fugitive.com^*-468x60web. ||fulhamfc.com/i/partner/ ||fullrip.net/images/download- ||fulltv.tv/pub_ ||funpic.de/layer.php? ||funpic.org/layer.php? ||fuse.tv/images/sponsor/ ||futbol24.com/f24/rek/$~xmlhttprequest ||fuzface.com/dcrtv/ad$domain=dcrtv.com ||fırstrowsports.eu/pu/ ||g.brothersoft.com^ ||gabzfm.com/images/banners/ ||gaccmidwest.org/uploads/tx_bannermanagement/ ||gaccny.com/uploads/tx_bannermanagement/ ||gaccsouth.com/uploads/tx_bannermanagement/ ||gaccwest.com/uploads/tx_bannermanagement/ ||gadget.co.za/siteimages/banners/ ||gadgetmac.com^*/sponsors/ ||gadgetshowlive.net^*/banners/ ||gaeatimes.com/ctad/ ||galatta.com^*/bannerimages/ ||galatta.com^*/banners/ ||game1games.com/exchange/ ||gameads.digyourowngrave.com^ ||gamecopyworld.com*/! ||gamecopyworld.com/games/i/if6.gif ||gamecopyworld.com/games/js/abd.js ||gamecopyworld.com^*/vg_160x120_ ||gamecopyworld.eu*/! ||gameknot.com/amaster.pl?j= ||gamemakerblog.com/gma/gatob.php ||gameplanet.co.nz^*-takeover.jpg ||gamerant.com/ads/ ||gamersbook.com^*/banners/ ||gameserpent.com/kit*.php ||gameserpent.com/vc*.php ||gamesforwork.com^*/dropalink_small.gif ||gamesfreez.com/banner/ ||gamesgames.com/vda/ ||gameshark.com^*/pageskin- ||gametrailers.com^*/webskin_ ||gamevid.com/13/ads/ ||gamingsquid.com/wp-content/banners/ ||ganool.com/pup.js ||ganool.com/wp-content/uploads/*/Javtoys300250..gif ||ganool.com/wp-content/uploads/*/matrix303.gif ||gappon.com/images/hot2.gif ||garrysmod.org/img/sad/ ||gasgoo.com/promo/ ||gateprep.com/templates/default/images/promo/ ||gawkerassets.com^*/background.jpg ||gaydarradio.com/userportal/miva/ ||gaynz.com/mysa/banners/ ||gaynz.gen.nz/mysa/banners/ ||gbatemp.net/images/ab/ ||gbrej.com/c/ ||gcnlive.com/assets/sponsors/ ||gcnlive.com/assets/sponsorsPlayer/ ||geckoforums.net/banners/ ||geeklab.info^*/billy.png ||gelbooru.com/lk.php$subdocument ||gelbooru.com/poll.php$subdocument ||gelbooru.com/protech.php$subdocument ||generalfiles.me^*/download_sponsored. ||gentoo.org/images/sponsors/ ||geocities.com/js_source/ ||geocities.yahoo.*/js/sq. ||geometria.tv/banners/ ||geoshopping.nzherald.co.nz^ ||gestetnerupdates.com^*/chesed-shel-emes-600x75.gif ||gestetnerupdates.com^*/eagle-sewer.gif ||gestetnerupdates.com^*/Gestetner-Miles.gif ||gestetnerupdates.com^*/perfect-auto-collision_banner.gif ||get.thefile.me^ ||getfoxyproxy.org/images/abine/ ||getprice.com.au/searchwidget.aspx?$subdocument ||getreading.co.uk/static/img/bg_takeover_ ||getresponse.com^$domain=wigflip.com ||getrichslowly.org/blog/img/banner/ ||getsurrey.co.uk^*/bg_takeover_ ||gfi.com/blog/wp-content/uploads/*-BlogBanner ||gfx.infomine.com^ ||ghacks.net/skin- ||ghafla.co.ke/images/banners/ ||ghafla.co.ke/images/bgmax/ ||ghananewsagency.org/assets/banners/ ||giftguide.savannahnow.com/giftguide/widgets/ ||gigaom2.files.wordpress.com^*-center-top$image ||girlguides.co.za/images/banners/ ||girlsgames.biz/games/partner*.php ||gizmochina.com/images/blackview.jpg ||gizmochina.com^*/100002648432985.gif ||gizmochina.com^*/kingsing-t8-advert.jpg ||gizmochina.com^*/landvo-l600-pro-feature.jpg ||glam.com^*/affiliate/ ||glamourviews.com/home/zones? ||glassdoor.com/getAdSlotContentsAjax.htm? ||gledaisport.com/ads/ ||globalsecurity.org/_inc/frames/ ||globaltimes.cn/desktopmodules/bannerdisplay/ ||glocktalk.com/forums/images/banners/ ||go4up.com/assets/img/d0.png ||go4up.com/assets/img/download-button.png ||goal.com^*/betting/$~stylesheet ||goal.com^*/branding/ ||goauto.com.au/mellor/mellor.nsf/toy$subdocument ||gokunming.com/images/prom/ ||gold-prices.biz/gold_trading_leader.gif ||gold-prices.biz^*_400x300.gif ||gold1013fm.com/images/background/ ||gold1013fm.com/promotion/ ||goldenskate.com/sponsors/ ||golf365.co.za^*/site-bg- ||golf365.com^*/site-bg- ||gomlab.com/img/banner/ ||gomtv.net/img/ad/ ||gonzagamer.com/uci/popover.js ||goo.gl^$subdocument,domain=backin.net|uploadlw.com ||goodanime.net/images/crazy*.jpg ||goodgearguide.com.au/files/skins/ ||google.com/jsapi?autoload=*%22ads%22$script,domain=youtube.com ||googleusercontent.com^*/s220/$domain=activistpost.com ||googleusercontent.com^*/s468/$domain=activistpost.com ||gooster.co.uk/js/ov.js.php ||gopride.com^*/banners/ ||gospel1190.net/rotatorimages/ ||gotupload.com^$subdocument,domain=hulkshare.com ||gov-auctions.org^*/banner/ ||gowilkes.com/cj/ ||gowilkes.com/other/ ||gq.co.za^*/sitetakeover/ ||grammar-monster.com/scripts/$subdocument ||grapevine.is/media/flash/*.swf ||graphic.com.gh/images/banners/ ||greatandhra.com/images/*_ga_ ||greatdeals.co.ke/images/banners/ ||greaterkashmir.com/adds_ ||greatgirlsgames.com/100x100.php ||greatgirlsgames.com/a/skyscraper.php ||green.virtual-nights.com^ ||greenoptimistic.com/images/electrician2.png ||greyorgray.com/images/Fast%20Business%20Loans%20Ad.jpg ||greyorgray.com/images/hdtv-genie-gog.jpg ||gruntig2008.opendrive.com^$domain=gruntig.net ||gsprating.com/gap/image.php? ||gtop100.com/a_images/show-a.php? ||gtsplus.net*/panbottom.html ||gtsplus.net*/pantop.html ||gtweekly.com/images/banners/ ||guardian.bz/images/banners/ ||gulf-daily-news.com/180x150.htm ||gulfnews.com^*/channelSponsorImage/ ||gumtree.com^*/dart_wrapper_ ||guns.ru^*/banner/ ||guns.ru^*/banners/ ||gurgle.com/modules/mod_m10banners/ ||guru99.com/images/adblocker/ ||gwinnettdailypost.com/1.iframe.asp? ||h33t.to/images/button_direct.png ||ha.ckers.org/images/fallingrock-bot.png ||ha.ckers.org/images/nto_top.png ||ha.ckers.org/images/sectheory-bot.png ||hackingchinese.com/media/hcw4.png ||hackingchinese.com/media/hellochinese.jpg ||hackingchinese.com/media/pleco.png ||hackingchinese.com/media/skritter5.jpg ||hardwareheaven.com/styles/*/frontpage/backdrop.jpg ||hardwareheaven.com/wp-content/*_skin_ ||hawaiireporter.com^*-300x250.jpg ||hawaiireporter.com^*/463%C3%9757-Kamaaina.jpg ||hawaiireporter.com^*/js.jpg ||hawaiireporter.com^*/upandruningy.jpg ||hawaiireporter.com^*/winnerscampad.jpg ||hawaiireporter.com^*_300x400.jpg ||hawkesbay.co.nz/images/banners/ ||hawkesbaytoday.co.nz/nz_regionals/marketplace/ ||hcdn.co/scripts/shadowbox/shadowbox.js$domain=shared.sx ||hd-bb.org^*/dl4fbanner.gif ||hdtvtest.co.uk/image/partner/$image ||hdtvtest.co.uk^*/pricerunner.php ||headlineplanet.com/home/box.html ||headlineplanet.com/home/burstbox.html ||healthfreedoms.org/assets/swf/320x320_ ||heatworld.com/images/*_83x76_ ||heatworld.com/upload/takeovers/ ||heatworld.com^*_300x160.jpg ||helsinkitimes.fi^*/banners/ ||hentai2read.com/ios/swf/ ||hentaistream.com/wp-includes/images/$object ||heraldm.com/hb/imad/ ||heraldm.com/iframe/ ||heraldm.com^*/banner/ ||heraldsun.com.au^*/images/sideskins- ||herold.at/fs/orgimg/*.swf?baseurl=http%3a%2f%2fwww.*&linktarget=_blank$object ||herold.at/images/dealofday.swf ||herold.at^*.swf?*&linktarget=_blank ||herzeleid.com/files/images/banners/ ||hexupload.com^*.gif$domain=uploadbaz.com ||hickoryrecord.com/app/deal/ ||highdefjunkies.com/images/misc/kindlejoin.jpg ||highdefjunkies.com^*/cp.gif ||highdefjunkies.com^*/monoprice.jpg ||highdefjunkies.com^*/sponsor.jpg ||hipforums.com/images/banners/ ||hipforums.com/newforums/calendarcolumn.php?cquery=bush ||hitechlegion.com/images/banners/ ||hkclubbing.com/images/banners/ ||hockeybuzz.com/mb/b? ||hollywoodbackwash.com/glam/ ||holyfamilyradio.org/banners/ ||holyfragger.com/images/skins/ ||homad-global-configs.schneevonmorgen.com^$domain=muzu.tv ||homeschoolmath.net/a/ ||honda-tech.com/*-140x90.gif ||hongfire.com/banner/ ||hongkongindians.com/advimages/ ||horizonsunlimited.com/alogos/ ||horriblesubs.info/playasia ||hostingbulk.com/aad.html ||hostingbulk.com/zad.html ||hostratings.co.uk/zeepeel. ||hostsearch.com/creative/ ||hot-scene.com/cpop.js ||hotbollywoodactress.net/ff2.gif ||hotbollywoodactress.net/freedatingindia.gif ||hotfile.com^*/banners/ ||hotfilesearch.com/includes/images/mov_ ||hotfiletrend.com/dlp.gif ||hotgamesforgirls.com/html/$subdocument ||hothardware.com/pgmerchanttable.aspx? ||hothardware.com^*_staticbanner_*.jpg ||houndmirror.com/images/XmkuP.gif ||houseoftravel.co.nz/flash/banner/ ||howtogeek.com/go/ ||howtogermany.com/banner/ ||howwemadeitinafrica.com^*/dhl-hdr.gif ||hpfanficarchive.com/freecoins2.jpg ||hqfooty.tv/ad ||htmldog.com/r10/flowers/ ||http.atlas.cdn.yimg.com/yamplus/video_*.mp4?$object-subrequest,domain=yahoo.com ||hulkfile.eu/images/africa.gif ||hulkload.com/b/ ||hulkload.com/recommended/ ||hulkshare.com/promo/ ||hulkshare.com^*/adsmanager.js ||hulkshare.oncdn.com^*/removeads. ||hulu.com/beacon/*=adauditerror ||hulu.com/v3/revenue/ ||hummy.org.uk^*/brotator/ ||hurriyetdailynews.com/images/*_100x250_ ||hwbot.org/banner.img ||hwinfo.com/images/lansweeper.jpg ||hwinfo.com/images/se2banner.png ||hypemagazine.co.za/assets/bg/ ||i-sgcm.com/pagetakeover/ ||i-tech.com.au^*/banner/ ||i.com.com^*/vendor_bg_ ||i.i.com.com/cnwk.1d/*/tt_post_dl.jpg ||i.neoseeker.com/d/$subdocument ||i3investor.com^*/offer_ ||i3investor.com^*/partner/ ||ians.in/iansad/ ||ibanners.empoweredcomms.com.au^ ||ibizaworldclubtour.net/wp-content/themes/ex-studios/banner/ ||ibnlive.in.com^*/ibn_*_banner_ ||ibrod.tv/ib.php ||ibsrv.net/*214x30. ||ibsrv.net/*_215x30. ||ibsrv.net/*_215x30_ ||ibsrv.net/*forumsponsor$domain=audiforums.com ||ibsrv.net/royalpurple/$domain=audiforums.com ||ibsrv.net/sponsors/ ||ibtimes.com/banner/ ||ibtimes.com^*&popunder ||ibtimes.com^*/sponsor_ ||iceinspace.com.au/iisads/ ||icelandreview.com^*/auglysingar/ ||iconeye.com/images/banners/ ||icrt.com.tw/downloads/banner/ ||ictv-ic-ec.indieclicktv.com/media/videos/$object-subrequest,domain=twitchfilm.com ||icydk.com^*/title_visit_sponsors. ||iddin.com/img/chatwing_banner. ||iddin.com/img/chatwing_banner_ ||idesitv.com^*/loadbanners. ||idg.com.au/files/skins/ ||idg.com.au/images/*_promo$image ||idg.com.au^*_skin.jpg ||ientrymail.com/webheadtools$domain=webpronews.com ||ifilm.com/website/*-skin- ||iframe.travel.yahoo.com^ ||iftn.ie/images/data/banners/ ||ijn.com/images/banners/ ||ijoomla.com/aff/banners/ ||ilcorsaronero.info/home.gif ||ilikecheats.net/images/$image,domain=unknowncheats.me ||iload.to/img/ul/impopi.js ||iloveim.com/cadv ||imads.rediff.com^ ||imagebam.com/download/$image,domain=ganool.com ||imagebam.com/download_button.png ||imagebam.com/img/coolstuffbro.jpg ||imagefruit.com/includes/js/bgcont.js ||imagefruit.com/includes/js/ex.js ||imagefruit.com/includes/js/layer.js ||imagepix.org/Images/imageput.jpg ||imageporter.com/hiokax.js ||imageporter.com/micromoo.html ||imageporter.com/someo.html ||imagerise.com/ir.js ||imagerise.com/ir2.js ||images-amazon.com/images/*/browser-scripts/da- ||images-amazon.com/images/*/browser-scripts/dae- ||images-amazon.com/images/*/da-us/da-$script ||images-amazon.com^*/marqueepushdown/ ||images.bitreactor.to/designs/ ||images.globes.co.il^*/fixedpromoright. ||images.sharkscope.com/acr/*_Ad- ||images.sharkscope.com/everest/twister.jpg ||imageshack.us/images/contests/*/lp-bg.jpg ||imageshack.us/ym.php? ||imagesnake.com^*/oc.js ||imagetoupload.com/images/87633952425570896161.jpg ||imagevenue.com/interstitial. ||imcdb.org/res/cth_ ||imdb.com/images/*/scriptloader.$subdocument ||img*.i-comers.com^ ||imgah.com/traffic$subdocument ||imgburn.com/images/ddigest_ ||imgburn.com/images/your3gift.gif ||imgcarry.com^*/oc.js ||imgchili.net/js/showa.js ||imgchili.net/lj.js ||imgur.com/i2iBMaD.gif$domain=cpahero.com ||imgur.com/include/zedoinviewstub1621.html ||imouto.org/images/jlist/ ||imouto.org/images/mangagamer/ ||impactradio.co.za^*/banners/ ||impulsedriven.com/app_images/wallpaper/ ||in.com/addIframe/ ||in.com^*/170x50_ ||inanyevent.ch/images/banners/ ||incentivetravel.co.uk/images/banners/ ||indeed.com/ads/ ||independent.co.ug/images/banners/ ||independent.co.uk/kelkoo/ ||independent.co.uk/multimedia/archive/$subdocument ||independent.co.uk^*/300unit/ ||independent.co.uk^*/partners/ ||indepthafrica.com^*/Banner-canreach.gif ||india.com/ads/jw/ova-jw.swf$object-subrequest ||india.com/zeenews_head2n.jpg ||india.com^*-sponsor. ||indiainfoline.com/wc/ads/ ||indianexpress.com^*/banner/ ||indiantelevision.com/banner/ ||indiatimes.com/articleshow_google_$subdocument ||indiatimes.com/google$subdocument ||industryabout.com/images/banners/ ||info.break.com^*/sponsors/ ||infobetting.com/b/ ||infobetting.com/bookmaker/ ||infoq.com^*/banners/ ||informe.com/img/banner_ ||infosecisland.com/ajax/viewbanner/ ||infoseek.co.jp/isweb/clip.html ||ingdirect.com^*/adwizard/ ||injpn.net/images/banners/ ||inkscapeforum.com/images/banners/ ||inquirer.net/wp-content/themes/news/images/wallpaper_ ||insidebutlercounty.com/images/100- ||insidebutlercounty.com/images/160- ||insidebutlercounty.com/images/180- ||insidebutlercounty.com/images/200- ||insidebutlercounty.com/images/300- ||insidebutlercounty.com/images/468- ||insidedp.com/images/banners/ ||insidehw.com/images/banners/ ||insideyork.co.uk/assets/images/sponsors/ ||inspirefirst.com^*/banners/ ||intel.com/sites/wap/global/wap.js ||intellicast.com/outsidein.js ||intellicast.com/travel/cheapflightswidget.htm ||intelseek.com/intelseekads/ ||interest.co.nz/banners/ ||interest.co.nz^*_skin. ||interest.co.nz^*_skin_ ||interfacelift.com/inc_new/$subdocument ||interfacelift.com^*/artistsvalley_160x90_ ||international.to/600.html ||international.to/large.html ||international.to/link_unit.html ||internationalmeetingsreview.com//uploads/banner/ ||intoday.in/btstryad.html ||ip-adress.com/i/ewa/ ||ip-adress.com/superb/ ||ip-ads.de^$domain=zattoo.com ||ipaddress.com/banner/ ||ipinfodb.com/img/adds/ ||iptools.com/sky.php ||irctctourism.com/ttrs/railtourism/Designs/html/images/tourism_right_banners/*DealsBanner_ ||irishamericannews.com/images/banners/ ||irishdev.com/files/banners/ ||irishdictionary.ie/view/images/ispaces-makes-any-computer.jpg ||irishracing.com/graphics/books ||ironmagazine.com^*/banners.php ||ironspider.ca/pics/hostgator_green120x600.gif ||ironsquid.tv/data/uploads/sponsors/ ||irv2.com/attachments/banners/ ||irv2.com/forums/*show_banner ||irv2.com/images/sponsors/ ||isitdownrightnow.com/graphics/speedupmypc*.png ||isitnormal.com/img/iphone_hp_promo_wide.png ||islamicfinder.org/cimage/ ||islamicfocus.co.za/images/banners/ ||island.lk/userfiles/image/danweem/ ||isportconnect.com//images/banners/ ||israeldefense.com/_Uploads/dbsBanners/ ||israelidiamond.co.il^*/bannerdisplay.aspx? ||israeltoday.co.il^*/promo/ ||isup.me/images/dotbiz_banner.jpg ||isxdead.com/images/showbox.png ||italiangenealogy.com/images/banners/ ||itpro.co.uk/images/skins/ ||itv.com/adexplore/*/config.xml ||itv.com/priority/$object-subrequest,domain=u.tv ||itweb.co.za/banners/ ||itweb.co.za/logos/ ||itweb.co.za/sidelogos/ ||itweb.co.za^*sponsoredby ||itwebafrica.com/images/logos/ ||itworld.com/slideshow/iframe/topimu/ ||iurfm.com/images/sponsors/ ||iwebtool.com^*/bannerview.php ||ixquick.nl/graphics/banner_ ||jamaica-gleaner.com/images/promo/ ||jame-world.com^*/adv/ ||jango.com/assets/promo/1600x1000- ||javamex.com/images/AdFrenchVocabGamesAnim.gif ||javascript-coder.com^*/form-submit-larger.jpg ||javascript-coder.com^*/make-form-without-coding.png ||jayisgames.com/maxcdn_160x250.png ||jazzandblues.org^*/iTunes_ ||jdownloader.org/_media/screenshots/banner.png ||jdownloader.org^*/smbanner.png ||jebril.com/sites/default/files/images/top-banners/ ||jewishexponent.com^*/banners/ ||jewishnews.co.uk^*-banner- ||jewishnews.co.uk^*-banner. ||jewishnews.co.uk^*/banner ||jewishtimes-sj.com/rop/ ||jewishtribune.ca^*/banners/ ||jewishvoiceny.com/ban2/ ||jewishyellow.com/pics/banners/ ||jheberg.net/img/mp.png ||jillianmichaels.com/images/publicsite/advertisingslug.gif ||johnbridge.com/vbulletin/banner_rotate.js ||johnbridge.com/vbulletin/images/tyw/cdlogo-john-bridge.jpg ||johnbridge.com/vbulletin/images/tyw/wedi-shower-systems-solutions.png ||johngaltfla.com/wordpress/wp-content/uploads/*/jmcs_specaialbanner.jpg ||johngaltfla.com/wordpress/wp-content/uploads/*/TB2K_LOGO.jpg ||joindota.com/wp-content/*.png$image ||jokertraffic.com^$domain=4fuckr.com ||joomladigger.com/images/banners/ ||journal-news.net/annoyingpopup/ ||journeychristiannews.com/images/banners/ ||joursouvres.fr^*/pub_ ||jozikids.co.za/uploadimages/*_140x140_ ||jozikids.co.za/uploadimages/140x140_ ||jpupdates.com^*/divorce_coach_rosenberg.gif ||jpupdates.com^*/jupdates.gif ||jpupdates.com^*/Mesamche-lev-Auction.gif ||jpupdates.com^*/PAL-DANS- ||jumptags.com/joozit/presentation/images/banners/ ||junocloud.me/promos/ ||just-download.com/banner/ ||justsomething.co/wp-content/uploads/*-250x250. ||kaieteurnewsonline.com/revenue/ ||kamcity.com/banager/banners/ ||kamcity.com/menu/banners/ ||kansascity.com/images/touts/ds_ ||kassfm.co.ke/images/moneygram.gif ||kat-ads.torrenticity.com^ ||kavkisfile.com/images/ly-mini.gif ||kavkisfile.com/images/ly.gif ||kbcradio.eu/img/banner/ ||kblx.com/upload/takeover_ ||kcrw.com/collage-images/amazon.gif ||kcrw.com/collage-images/itunes.gif ||kdoctv.net/images/banners/ ||keenspot.com/images/headerbar- ||keepvid.com/images/ilivid- ||kendrickcoleman.com/images/banners/ ||kentonline.co.uk/weatherimages/Britelite.gif ||kentonline.co.uk/weatherimages/SEW.jpg ||kentonline.co.uk/weatherimages/sponsor_ ||kephyr.com/spywarescanner/banner1.gif ||kermit.macnn.com^ ||kewlshare.com/reward.html ||kexp.org^*/sponsor- ||kexp.org^*/sponsoredby. ||keygen-fm.ru/images/*.swf ||kfog.com^*/banners/ ||khaleejtimes.com/imgactv/Umrah%20-%20290x60%20-%20EN.jpg ||khaleejtimes.com/imgactv/Umrah-Static-Background-Gutters-N.jpg ||khon2.com^*/sponsors/ ||kickasstorrent.ph/kat_adplib.js ||kickoff.com/images/sleeves/ ||kingfiles.net/images/bt.png ||kingofsat.net/pub/ ||kinox.to/392i921321.js ||kinox.to/com/ ||kinox.tv/g.js ||kirupa.com/supporter/ ||kitco.com/ssi/dmg_banner_001.stm ||kitco.com/ssi/home_ox_deanmg.stm ||kitco.com/ssi/market_ox_deanmg.stm ||kitco.com^*/banners/ ||kitguru.net/?kitguru_wrapjs=1&ver= ||kitguru.net/wp-content/banners/ ||kitguru.net/wp-content/wrap.jpg ||kitz.co.uk/files/jump2/ ||kjlhradio.com^*-300x250. ||kjlhradio.com^*/banners/ ||kjul1047.com^*/clientgraphics/ ||klav1230am.com^*/banners/ ||kleisauke.nl/static/img/bar.gif ||klfm967.co.uk/resources/creative/ ||klkdccs.net/pjs/yavli-tools.js ||klm.com^*/fls_redirect.html ||knbr.com^*/banners/ ||kncminer.com/userfiles/image/250_240.jpg ||knowfree.net^*/ezm125x125.gif ||knowledgespeak.com/images/banner/ ||knowthecause.com/images/banners/ ||knpr.org/common/sponsors/ ||kob.com/kobtvimages/flexhousepromotions/ ||komando.com^*/k2-interstitial.min.js? ||kompas.com/js_kompasads.php ||kongregate.com/images/help_devs_*.png ||kontraband.com/media/takeovers/ ||koraliga.com/open.js ||koreanmovie.com/img/banner/banner.jpg ||koreatimes.co.kr/ad/ ||koreatimes.co.kr/images/bn/ ||koreatimes.co.kr/upload/ad/ ||koreatimes.co.kr/www/images/bn/ ||kovideo.net^*.php?user_ ||krapps.com^*-banner- ||krebsonsecurity.com/b-ga/ ||krebsonsecurity.com/b-kb/ ||kron.com/uploads/*-ad-$image ||krzk.com/uploads/banners/ ||ksstradio.com/wp-content/banners/ ||kstp.com^*/flexhousepromotions/ ||ktradionetwork.com^*/banners/ ||kuiken.co/static/w.js ||kukuplay.com/upload/*.swf ||kvcr.org^*/sponsors/ ||kwanalu.co.za/upload/ad/ ||kxlh.com/images/banner/ ||kyivpost.com/media/banners/ ||l.yimg.com/a/i/*_wallpaper$image ||l.yimg.com/ao/i/ad/ ||l.yimg.com/mq/a/ ||l4dmaps.com/i/right_dllme.gif ||l4dmaps.com/img/right_gameservers.gif ||labtimes.org/banner/ ||lagacetanewspaper.com^*/banners/ ||lake-link.com/images/sponsorLogos/ ||lancasteronline.com^*/done_deal/ ||lancasteronline.com^*/weather_sponsor.gif ||lankabusinessonline.com/images/banners/ ||laobserved.com/tch-ad.jpg ||laptopmag.com/images/sponsorships/ ||laredodaily.com/images/banners/ ||lastminute.com^*/universal.html? ||lasttorrents.org/pcmadd.swf ||latex-community.org/images/banners/ ||lawdepot.com/affiliate/ ||lazygamer.net/kalahari.gif ||lazygirls.info/click.php ||leader.co.za/leadership/banners/ ||leagueunlimited.com/images/rooty/ ||learnspanishtoday.com/aff/img/banners/ ||lecydre.com/proxy.png ||legalbusinessonline.com/popup/albpartners.aspx ||lens101.com/images/banner.jpg ||lespagesjaunesafrique.com/bandeaux/ ||letitbit.net/images/other/inst_forex_ ||letswatchsomething.com/images/filestreet_banner.jpg ||lfcimages.com^*/partner- ||lfcimages.com^*/sponsor- ||lfgcomic.com/wp-content/uploads/*/PageSkin_ ||libertyblitzkrieg.com/wp-content/uploads/2012/09/cc200x300.gif? ||licensing.biz/media/banners/ ||life.imagepix.org^ ||lifeinqueensland.com/images/156x183a_ ||lifetips.com/sponsors/ ||limesurvey.org/images/banners/ ||linguee.com/banner/ ||linkcentre.com/top_fp.php ||linkfm.co.za/images/banners/ ||linkmoon.net/banners/ ||linksafe.info^*/mirror.png ||linksave.in/img/downloadbutton_alt.png ||linksave.in/img/downloadbutton_hs.png ||linksave.in/img/downloadbutton_sh.png ||linksave.in^*/downloadbutton_highspeed.png ||linksrank.com/links/ ||linuxinsider.com/images/sda/ ||linuxmint.com/img/sponsor/ ||linuxmint.com/pictures/sponsors/ ||linuxsat-support.com/vsa_banners/ ||linuxtopia.org/includes/$subdocument ||lionsrugby.co.za^*/sponsors. ||liquidcompass.net/playerapi/redirect/ ||liquidcompass.net^*/purchase_ ||littleindia.com/files/banners/ ||live-proxy.com/hide-my-ass.gif ||live-proxy.com/vectrotunnel-logo.jpg ||livejasmin.com/freechat.php ||liveonlinetv247.com/images/muvixx-150x50-watch-now-in-hd-play-btn.gif ||livescore.in/res/image/bookmaker-list.png ||livesearch.ninemsn.com.au^$subdocument ||livestream.com^*/overlay/ ||livetradingnews.com/wp-content/uploads/vamp_cigarettes.png ||livetv.ru/mb/ ||livetvcenter.com/satellitedirect_ ||livingscoop.com/vastload.php ||ll.a.hulu.com^ ||lmgtfy.com/s/images/ls_ ||localdirectories.com.au^*/bannerimages/ ||locanto.co.za/run/afcbackfill/ ||logoopenstock.com/img/banners/ ||logotv.com/content/skins/ ||loleasy.com/promo/ ||loleasy.com^*/adsmanager.js ||lolzbook.com/test/ ||london2012.com/img/sponsors/ ||london2012.com/imgml/partners/footer/ ||londonprivaterentals.standard.co.uk^ ||londonstockexchange.com^*/fx.gif ||lookbook.nu/show_leaderboard.html ||lookbook.nu/show_skyscraper.html ||lookbook.nu^*.html?$subdocument ||looky.hyves.org^ ||lowbird.com/lbpu.php ||lowbird.com/lbpun.php ||lowellsun.com/litebanner/ ||lowendbox.com/wp-content/themes/leb/banners/ ||lowyat.net/lowyat/lowyat-bg.jpg ||lowyat.net/mainpage/background.jpg ||lshunter.tv/images/bets/ ||lshunter.tv^*&task=getbets$xmlhttprequest ||lucianne.com^*_*.html ||luckyshare.net/images/1gotlucky.png ||luckyshare.net/images/2top.png ||luckyshare.net/images/sda/ ||luxury4play.com^*/ads/ ||lw1.gamecopyworld.com^$subdocument ||lw1.lnkworld.com^$subdocument ||lw2.gamecopyworld.com^ ||lycos.com/catman/ ||lygo.com/scripts/catman/ ||lyrics5ab.com/wp-content/add$subdocument ||lyricsfreak.com^*/overlay.js ||m-w.com/creative.php ||m4carbine.net/tabs/ ||macaudailytimes.com.mo/files/banners/ ||macaunews.com.mo/images/stories/banners/ ||macblurayplayer.com/image/amazon- ||machovideo.com/img/site/postimg2/rotate.php ||macintouch.com/images/amaz_ ||macintouch.com/images/owc_ ||maciverse.mangoco.netdna-cdn.com^*banner ||macmillandictionary.com/info/frame.html?zone= ||macobserver.com/js/givetotmo.js ||macobserver.com^*/deal_brothers/ ||macupdate.com/js/google_service.js ||macworld.co.uk^*/textdeals/ ||macworld.com/ads/ ||madamenoire.com/wp-content/*_Reskin-$image ||mads.dailymail.co.uk^ ||madskristensen.net/discount2.js ||madville.com/afs.php ||mail.yahoo.com/mc/md.php? ||mailinator.com/images/abine/leaderboard- ||mailinator.com^*/clickbanner.jpg ||majorgeeks.com/aff/ ||majorgeeks.com/images/*_336x280.jpg ||majorgeeks.com/images/download_sd_ ||majorgeeks.com/images/mb-hb-2.jpg ||majorgeeks.com/images/mg120.jpg ||majorgeeks.com^*/banners/ ||makeagif.com/parts/fiframe.php ||malaysiabay.org^*/creative.js ||malaysiabay.org^*creatives.php? ||malaysiakini.com/misc/banners/ ||maltatoday.com.mt/ui_frontend/display_external_module/ ||malwaredomains.com/ra.jpg ||mangafox.com/media/game321/ ||mangareader.net/images/800-x-100 ||mangarush.com/xtend.php ||mangaupdates.com/affiliates/ ||manhattantimesnews.com/images/banners/ ||mani-admin-plugin.com^*/banners/ ||maniastreaming.com/pp2/ ||manicapost.com^*/banners/ ||manilatimes.net/images/banners/ ||manutd.com^*/Sponsors/ ||manxradio.com^*/banners_ ||mapsofindia.com/widgets/tribalfusionboxadd.html ||maravipost.com/images/banners/ ||marineterms.com/images/banners/ ||marketingpilgrim.com/wp-content/uploads/*/trackur.com- ||marketingsolutions.yahoo.com^ ||marketingupdate.co.za/temp/banner_ ||marketintelligencecenter.com/images/brokers/ ||marketnewsvideo.com/etfchannel/evfad1.gif ||marketnewsvideo.com/mnvport160.gif ||marketplace.org^*/support_block/ ||mary.com/728_header.php ||mashable.com/tripleclick.html ||mathforum.org/images/tutor.gif ||mauritiusnews.co.uk/images/banners/ ||maxconsole.com/maxconsole/banners/ ||maxgames.com^*/sponsor_ ||mb.hockeybuzz.com^ ||mccont.com/campaign%20management/ ||mccont.com/sda/ ||mccont.com/takeover/ ||mcjonline.com/filemanager/userfiles/banners/ ||mcnews.com.au/banners/ ||mcsesports.com/images/sponsors/ ||mcstatic.com^*/billboard_ ||mcvuk.com/static/banners/ ||mealsandsteals.sandiego6.com^ ||meanjin.com.au/static/images/sponsors.jpg ||mechodownload.com/forum/images/affiliates/ ||medhelp.org/hserver/ ||media-delivery.armorgames.com^ ||media-imdb.com/images/*/mptv_banner_ ||media-imdb.com^*/affiliates/ ||media-imdb.com^*/clicktale-$script ||media-mgmt.armorgames.com^ ||media.abc.go.com^*/callouts/ ||media.mtvnservices.com/player/scripts/mtvn_player_control.js$domain=spike.com ||mediafire.com/images/rockmelt/ ||mediafire.com/templates/linkto/ ||mediafire.com^*/linkto/default-$subdocument ||mediafire.com^*/rockmelt_tabcontent.jpg ||mediafire.re/popup.js ||mediamgr.ugo.com^ ||mediaspanonline.com/images/buy-itunes.png ||mediaspanonline.com/inc.php?uri=/&bannerPositions= ||mediaspanonline.com^*_Background.$domain=farmingshow.com ||mediaspanonline.com^*_Background_$domain=farmingshow.com|radiosport.co.nz ||mediaticks.com/bollywood.jpg ||mediaticks.com/images/genx-infotech.jpg ||mediaticks.com/images/genx.jpg ||mediaupdate.co.za/temp/banner_ ||mediaweek.com.au/storage/*_234x234.jpg? ||medicaldaily.com/views/images/banners/ ||meetic.com/js/*/site_under_ ||megashares.com/cache_program_banner.html ||megaswf.com/file/$domain=gruntig.net ||megauploadtrend.com/iframe/if.php? ||meinbonusxxl.de^$domain=xup.in ||meizufans.eu/efox.gif ||meizufans.eu/merimobiles.gif ||meizufans.eu/vifocal.gif ||memory-alpha.org/__varnish_liftium/ ||memorygapdotorg.files.wordpress.com^*allamerican3.jpg$domain=memoryholeblog.com ||menafn.com^*/banner_ ||mentalfloss.com^*-skin- ||merriam-webster.com/creative.php? ||merriam-webster.com^*/accipiter.js ||messianictimes.com/images/1-13/ba_mhfinal_ ||messianictimes.com/images/4-13/reach.jpg ||messianictimes.com/images/banners/ ||messianictimes.com/images/Israel%20Today%20Logo.png ||messianictimes.com/images/Jews%20for%20Jesus%20Banner.png ||messianictimes.com/images/MJBI.org.gif ||messianictimes.com/images/Word%20of%20Messiah%20Ministries1.png ||meteomedia.com^*&placement ||meteovista.co.uk/go/banner/ ||meteox.co.uk/bannerdetails.aspx? ||meteox.com/bannerdetails.aspx? ||metradar.ch^*/banner_ ||metrolyrics.com/js/min/tonefuse.js ||metromedia.co.za/bannersys/banners/ ||mfcdn.net/media/*left ||mfcdn.net/media/*right ||mfcdn.net/media/game321/$image ||mgid.com/ban/ ||mgnetwork.com/dealtaker/ ||mhvillage.com/ppc.php? ||mi-pro.co.uk/banners/ ||miamiherald.com^*/dealsaver/ ||miamiherald.com^*/teamfanshop/ ||micast.tv/clean.php ||michronicleonline.com/images/banners/ ||middle-east-online.com^*/meoadv/ ||midlandsradio.fm/bms/ ||mightyupload.com/popuu.js ||mikejung.biz/images/*/728x90xLiquidWeb_ ||milanounited.co.za/images/sponsor_ ||mindfood.com/upload/images/wallpaper_images/ ||miniclipcdn.com/images/takeovers/ ||mininova.org/js/vidukilayer.js ||minnpost.com^*/sponsor/ ||mirror.co.uk^*/gutters/ ||mirror.co.uk^*/sponsors/ ||mirror.co.uk^*_promos_ ||mirrorcreator.com/js/mpop.js ||mirrorcreator.com/js/pu_ad.js ||mirrorstack.com/?q=r_ads ||misterwhat.co.uk/business-company-300/ ||mixfm.co.za/images/banner ||mixfm.co.za^*/tallspon ||mixx96.com/images/banners/ ||mizzima.com/images/banners/ ||mlb.com/images/*_videoskin_*.jpg ||mlb.com^*/sponsorship/ ||mlg-ad-ops.s3.amazonaws.com^$domain=majorleaguegaming.com ||mmoculture.com/wp-content/uploads/*-background- ||mmorpg.com/images/skins/ ||mmosite.com/sponsor/ ||mnn.com/sites/*/popups/AllstatePopup$script ||mnn.com^*/120x60/ ||mob.org/banner/ ||mobilephonetalk.com/eurovps.swf ||mochiads.com/srv/ ||moneycontrol.co.in/mcjs/10promo/ ||moneymakerdiscussion.com/mmd-banners/ ||moneymedics.biz/upload/banners/ ||monitor.co.ug/image/view/*/120/ ||monitor.co.ug/image/view/*/468/ ||monkeygamesworld.com/images/banners/ ||monster.com/null&pp ||morefmphilly.com^*/sponsors/ ||morefree.net/wp-content/uploads/*/mauritanie.gif ||morningstaronline.co.uk/offsite/progressive-listings/ ||motorcycles-motorbikes.com/pictures/sponsors/ ||motorhomefacts.com/images/banners/ ||motortrader.com.my/skinner/ ||motorweek.org^*/sponsor_logos/ ||mountainbuzz.com/attachments/banners/ ||mousesteps.com/images/banners/ ||mouthshut.com^*/zedo.aspx ||movie2k.tl/layers/ ||movie2k.tl/serve.php ||movie4k.to/*.js ||movie4k.tv/e.js ||moviewallpaper.net/js/mwpopunder.js ||movizland.com/images/banners/ ||movstreaming.com/images/edhim.jpg ||movzap.com/aad.html ||movzap.com/zad.html ||mp.adverts.itv.com/adexplore/*.swf?$object-subrequest ||mp.adverts.itv.com/priority/*.mp4$object-subrequest ||mp3.li/images/md_banner_ ||mp3mediaworld.com*/! ||mp3s.su/uploads/___/djz_to.png ||mp3skull.com/call_banner_exec_new. ||msecnd.net/scripts/compressed.common.lib.js?$domain=firedrive.com|sockshare.com ||msn.com/?adunitid ||msw.ms^*/jquery.MSWPagePeel- ||mtbr.com/ajax/hotdeals/ ||mtv.co.uk^*/btn_itunes.png ||mtvnimages.com/images/skins/$image ||muchmusic.com/images/*-skin.png ||muchmusic.com^*/bigbox_frame_resizer.html ||muchmusic.com^*/leaderboard_frame_obiwan.html ||multiupload.biz/r_ads2 ||murdermysteries.com/banners-murder/ ||music.yahoo.com/get-free-html ||musicmaza.com/bannerdyn ||musicplayon.com/banner? ||musicremedy.com/banner/ ||musictarget.com*/! ||mustangevolution.com/images/300x100_ ||mustangevolution.com^*/banner/ ||mustangevolution.com^*/banners/ ||muthafm.com^*/partners.png ||muzu.tv/player/muzutv_homadconfig. ||my-link.pro/rotatingBanner.js ||myam1230.com/images/banners/ ||mybroadband.co.za/news/wp-content/wallpapers/ ||mycentraljersey.com^*/sponsor_ ||myfax.com/free/images/sendfax/cp_coffee_660x80.swf ||myfpscheats.com/bannerimg.jpg ||mygaming.co.za/news/wp-content/wallpapers/ ||myiplayer.eu/ad ||mypbrand.com/wp-content/uploads/*banner ||mypiratebay.cl^$subdocument ||mypremium.tv^*/bpad.htm ||myretrotv.com^*_horbnr.jpg ||myretrotv.com^*_vertbnr.jpg ||myrls.me/open.js ||mysafesearch.co.uk/adds/ ||myshadibridalexpo.com/banner/ ||myspacecdn.com/cms/*_skin_ ||mysubtitles.com^*_banner.jpg ||mysuncoast.com/app/wallpaper/ ||mysuncoast.com^*/sponsors/ ||myway.com/gca_iframe.html ||mywot.net/files/wotcert/vipre.png ||naij.com^*/branding/ ||nairaland.com/dynamic/$image ||nation.co.ke^*_bg.png ||nation.lk^*/banners/ ||nation.sc/images/banners/ ||nation.sc/images/pub ||nationaljournal.com/js/njg.js ||nationalreview.com/images/display_300x600- ||nationalturk.com^*/banner ||nationmultimedia.com/home/banner/ ||nationmultimedia.com/new/js/nation_popup.js ||nativetimes.com/images/banners/ ||naukimg.com/banner/ ||nbr.co.nz^*-WingBanner_ ||nciku.com^*banner ||ncrypt.in/images/1.gif ||ncrypt.in/images/a/ ||ncrypt.in/images/banner ||ncrypt.in/images/useful/ ||ncrypt.in/javascript/jquery.msgbox.min.js ||ncrypt.in^*/layer.$script ||ndtv.com/widget/conv-tb ||ndtv.com^*/banner/ ||ndtv.com^*/sponsors/ ||nearlygood.com^*/_aff.php? ||nemesistv.info/jQuery.NagAds1.min.js ||neoseeker.com/a_pane.php ||neowin.net/images/atlas/aww ||nerej.com/c/ ||nesn.com/img/nesn-nation/bg- ||nesn.com/img/nesn-nation/header-dunkin.jpg ||nesn.com/img/sponsors/ ||netdna-cdn.com^$domain=modovideo.com|mooshare.biz ||netdna-cdn.com^*/tiwib-lootr-ad.png$domain=thisiswhyimbroke.com ||netindian.in/frontsquare*.php ||netspidermm.indiatimes.com^ ||netsplit.de/links/rootado.gif ||netupd8.com^*/ads/ ||network.sofeminine.co.uk^ ||networkwestvirginia.com/uploads/user_banners/ ||networx.com/widget.php?aff_id=$script ||newafricanmagazine.com/images/banners/ ||newalbumreleases.net/banners/ ||newburytoday.co.uk^*-WillisAinsworth1.gif ||newipnow.com/ad-js.php ||newoxfordreview.org/banners/ad- ||newpct.com/soporte/ ||news-leader.com^*/banner.js ||news-record.com/app/deal/ ||news.am/pic/bnr/ ||news.com.au/cs/*/bg-body.jpg ||news.com.au/news/vodafone/$object ||news.com.au^*-promo$image ||news.com.au^*/images/*-bg.jpg ||news.com.au^*/promos/ ||news.com.au^*/promotions/ ||news.com.au^*/public/img/p/$image ||newsbusters.org^*/banners/ ||newscdn.com.au^*/desktop-bg-body.png$domain=news.com.au ||newsday.co.tt/banner/ ||newsonjapan.com^*/banner/ ||newsreview.com/images/promo.gif ||newstatesman.com/sites/all/themes/*_1280x2000.$image ||newstrackindia.com/images/hairfallguru728x90.jpg ||newsudanvision.com/images/banners/ ||newsudanvision.com/images/Carjunctionadvert.gif ||newsvine.com//jenga/widget/ ||newsvine.com/jenga/widget/ ||newsweek.com^*interstitial.js ||newverhost.com/css/onload.js ||newverhost.com/css/pp.js ||newvision.co.ug/banners/ ||newvision.co.ug/rightsidepopup/ ||nextag.com^*/NextagSponsoredProducts.jsp? ||nextbigwhat.com/wp-content/uploads/*ccavenue ||nextstl.com/images/banners/ ||nfl.com/assets/images/hp-poweredby- ||nfl.com^*/page-background-image.jpg ||nflcdn.com^*/partner-type/$~stylesheet ||ngfiles.com/bg-skins/sponsored/skins/$domain=newgrounds.com ||ngohq.com/images/ad.jpg$~collapse ||ngrguardiannews.com/images/banners/ ||nigeriafootball.com/img/affiliate_ ||nigerianyellowpages.com/images/banners/ ||niggasbelike.com/wp-content/themes/zeecorporate/images/b.jpg ||nijobfinder.co.uk/affiliates/ ||nimbb.com^$domain=my.rsscache.com ||nirsoft.net/banners/ ||nitrobahn.com.s3.amazonaws.com/theme/getclickybadge.gif ||nmap.org/shared/images/p/$image ||nme.com/js/takeoverlay.js ||nme.com/themes/takeovers/ ||nmimg.net/css/takeover_ ||nodevice.com/images/banners/ ||noram.srv.ysm.yahoo.com^ ||northjersey.com^*_Sponsor. ||norwaypost.no/images/banners/ ||nosteam.ro^*/compressed.ggotab36.js ||nosteam.ro^*/gamedvprop.js ||nosteam.ro^*/messages.js ||nosteam.ro^*/messagesprop.js ||notalwaysromantic.com/images/banner- ||notdoppler.com^*-promo-homepageskin.png ||notdoppler.com^*-promo-siteskin. ||notebook-driver.com/wp-content/images/banner_ ||novamov.com/images/download_video.jpg ||nowgoal.com/images/foreign/ ||nowwatchtvlive.com/matomyads.php ||nowwatchtvlive.com/revenuehits.html ||ntdtv.com^*/adv/ ||nu2.nu^*/sponsor/ ||nu2.nu^*_banner. ||nufc.com/forddirectbanner.js ||nufc.com^*/altoonative_Cardiff.gif ||nufc.com^*/mjs-2013-11.png ||nufc.com^*/skyscraper.gif ||nufc.com^*/The%20Gate_NUFC.com%20banner_%2016.8.13.gif ||nufc.com^*_360x120.gif ||numberempire.com/images/b/ ||nutritionhorizon.com/content/banners/ ||nutritionhorizon.com/content/flash_loaders/$object ||nuttynewstoday.com/images/hostwink.jpg ||nuttynewstoday.com/images/percento-banner.jpg ||nuvo.net^*/FooterPromoButtons.html ||nyaa.se/ag ||nyaa.se/ah ||nyaa.se/ai ||nydailynews.com/img/sponsor/ ||nydailynews.com/PCRichards/ ||nydailynews.com^*-reskin- ||nymag.com/partners/ ||nymag.com/scripts/skintakeover.js ||nymag.com^*/metrony_ ||nypost.com^*/takeovers/ ||nyrej.com/c/ ||nyt.com^*-sponsor- ||nytimes.com/ads/ ||nytimes.com^*-sponsor- ||nzbindex.nl/images/banners/ ||nzbking.com/static/nzbdrive_banner.swf ||nznewsuk.co.uk/banners/ ||oanda.com/wandacache/wf-banner- ||oas.autotrader.co.uk^ ||oas.skyscanner.net^ ||oasc07.citywire.co.uk^ ||oascentral.chron.com^ ||oascentral.hosted.ap.org^ ||oascentral.newsmax.com^ ||objects.tremormedia.com/embed/swf/acudeo.swf$object-subrequest,domain=deluxemusic.tv.staging.ipercast.net ||oboom.com/assets/raw/$media,domain=oboom.com ||observer.com.na/images/banners/ ||observer.org.sz/files/banners/ ||observer.ug/images/banners/ ||ocforums.com/adj/ ||ocp.cbssports.com/pacific/request.jsp? ||oddschecker.com^*/takeover/ ||ohmygore.com/ef_pub*.php ||oilprice.com/images/banners/ ||oilprice.com/images/sponsors/ ||oilprice.com/oiopub/ ||okccdn.com/media/img/takeovers/ ||okcupid.com/daisy?$subdocument ||oldgames.sk/images/topbar/ ||omgpop.com/dc? ||on.net/images/gon_nodestore.jpg ||one-delivery.co.uk^*/sensitivedating.png ||onepieceofbleach.com/onepieceofbleach-gao- ||onionstatic.com/sponsored/ ||onlinekeystore.com/skin1/images/side- ||onlinemarketnews.org^*/silver300600.gif ||onlinemarketnews.org^*/silver72890.gif ||onlinenews.com.pk/onlinenews-admin/banners/ ||onlinerealgames.com/google$subdocument ||onlineshopping.co.za/expop/ ||onlygoodmovies.com/netflix.gif ||onvasortir.com/maximemo-pense-bete-ovs.png ||opednews.com^*/iframe.php? ||opencurrency.com/wp-content/uploads/*-aocs-sidebar-commodity-bank.png ||opensubtitles.org/gfx/banners_campaigns/ ||oprah.com^*-300x335.jpg ||optics.org/banners/ ||optimum.net/utilities/doubleclicktargeting ||oraclebroadcasting.com/images/enerfood-300x90.gif ||oraclebroadcasting.com/images/extendovite300.gif ||oraclebroadcasting.com/images/hempusa_330.gif ||originalfm.com/images/hotspots/ ||orissadiary.com/img/*-banner.gif ||orkut.gmodules.com^/promote.xml ||orlandosentinel2.com^*-sponsorship- ||osdir.com/ml/$subdocument ||oteupload.com/images/iLivid-download- ||ourmanga.com/funklicks ||outlookindia.com/image/banner_ ||outofaces.com/*.html$subdocument ||overclock3d.net/img/pcp.jpg ||ovfile.com/player/jwadplugin.swf$object-subrequest ||ow.ly^*/hootsuite_promo.jpg ||own3d.tv/lr/*.flv ||ox-d.sbnation.com^ ||ox-d.wetransfer.com^ ||ox.furaffinity.net^ ||oyetimes.com/join/advertisers.html ||ozqul.com^*/webbanners.png ||ozy.com/modules/_common/ozy/blade/ ||ozy.com/modules/_common/ozy/full_width/ ||ozy.com/modules/_common/ozy/pushdown/ ||ozy.com^*/interstitial/ ||p2pnet.net/images/$image ||pacificnewscenter.com/images/banners/ ||pagesinventory.com/_data/img/*_125x400_ ||paisalive.com/include/popup.js ||pakistantoday.com.pk^*/karachi_houston_PakistanToday.jpg ||paktribune.com^*/banner ||pan2.ephotozine.com^$image ||pandora.com^*/mediaserverPublicRedirect.jsp ||parade.com/images/skins/ ||paradoxwikis.com/Sidebar.jpg ||pardaphash.com/direct/tracker/add/ ||parlemagazine.com/images/banners/ ||partners-z.com^ ||pasadenajournal.com/images/banners/ ||patrickjames.com/images/$domain=askandyaboutclothes.com ||payplay.fm^*/mastercs.js ||pbs.org^*/sponsors/ ||pbsrc.com/sponsor/ ||pbsrc.com^*/sponsor/ ||pcadvisor.co.uk/graphics/sponsored/ ||pcauthority.com.au^*/skins/ ||pcmag.com/blogshome/logicbuy.js ||pcpro.co.uk/images/*_siteskin ||pcpro.co.uk/images/skins/ ||pcpro.co.uk^*/pcprositeskin ||pcpro.co.uk^*skin_wide. ||pcr-online.biz/static/banners/ ||pcworld.co.nz^*_siteskin_ ||pcworld.com/ads/ ||pcworld.com/images/*_vidmod_316x202_ ||pcworld.com/templates/video/popup.jsp?*&flv=/pcw/ads/ ||pe.com^*/biice2scripts.js ||pechextreme.com^*/banner. ||pechextreme.com^*/banners/ ||pedestrian.tv/_crunk/wp-content/files_flutter/ ||penguin-news.com/images/banners/ ||perezhilton.com/images/ask/ ||peruthisweek.com/uploads/sponsor_image/ ||petri.co.il/media/$image ||petri.co.il/wp-content/uploads/banner1000x75_ ||petri.co.il/wp-content/uploads/banner700x475_ ||pettube.com/images/*-partner. ||pgatour.com^*/featurebillboard_ ||pghcitypaper.com/general/modalbox/modalbox.js ||phantom.ie^*/banners/ ||phillytrib.com/images/banners/ ||phnompenhpost.com/images/stories/banner/ ||phnompenhpost.com^*/banner_ ||phonearena.com/images/banners/ ||phonebunch.com/images/flipkart_offers_alt.jpg ||phonescoop.com^*/a_tab.gif ||phoronix.com/phxforums-thread-show.php ||photo.net/equipment/pg-160^ ||photobucket.com/albums/cc94/dl4all/temp/enginesong.gif$domain=dl4all.com ||photosupload.net/photosupload.js ||phpbb.com/theme/images/bg_forumatic_front_page.png ||phpbb.com/theme/images/hosting/hostmonster-downloads.gif ||phpmotion.com/images/banners-webhosts/ ||phuket-post.com/img/a/ ||phuketgazette.net/banners/ ||phuketgazette.net^*/banners/ ||phuketwan.com/img/b/ ||physorg.com^*/addetect.js ||pickmeupnews.com/cfopop.js ||picsee.net/clk.js ||pinkbike.org^*/skins/ ||pinknews.co.uk/gsky. ||pinknews.co.uk/newweb/ ||piratefm.co.uk/resources/creative/ ||pirateproxy.nl/inc/ex.js ||pitchero.com^*/toolstation.gif ||pittnews.com/modules/mod_novarp/ ||pixhost.org/image/fik1.jpg ||planecrashinfo.com/images/advertize1.gif ||planetlotus.org/images/partners/ ||play4movie.com/banner/ ||playgames2.com/ban300- ||playgames2.com/default160x160.php ||playgames2.com/mmoout.php ||playgames2.com/rand100x100.php ||playgroundmag.net^*/wallpaperpgesp_$image ||playhd.eu^*.html|$subdocument ||playhub.com/js/popup-wide.js ||playlist.yahoo.com/makeplaylist.dll?$domain=au.tv.yahoo.com ||playtowerdefensegames.com/ptdg-gao-gamebox-homepage.swf ||plsn.com/images/PLSN-Bg1.jpg ||plunderguide.com/leaderboard-gor.html ||plunderguide.com/rectangle2.html ||plundermedia.com*rectangle- ||pmm.people.com.cn^ ||pocket-lint.com/images/bytemarkad. ||pocketpcaddict.com/forums/images/banners/ ||pogo.com/v/*/js/ad.js ||pokernews.com/b/ ||pokernews.com/preroll.php? ||police-car-photos.com/pictures/sponsors/ ||policeprofessional.com/files/banners- ||policeprofessional.com/files/pictures- ||politicalwire.com/images/*-sponsor.jpg ||politico.com^*_skin_ ||politicususa.com/psa/ ||politicususa.netdna-cdn.com/wp-content/uploads/shadowbox-js/$script,domain=politicususa.com ||pons.eu^*/lingeniobanner.swf ||pop-over.powered-by.justplayzone.com^ ||pornevo.com/events_ ||portcanaveralwebcam.com/images/ad_ ||portevergladeswebcam.com^*-Ad.jpg ||portevergladeswebcam.com^*-WebCamBannerFall_ ||portlanddailysun.me/images/banners/ ||portmiamiwebcam.com/images/sling_ ||porttechnology.org/images/partners/ ||positivehealth.com^*/BannerAvatar/ ||positivehealth.com^*/TopicbannerAvatar/ ||postadsnow.com/panbanners/ ||postcrescent.com^*/promos/ ||postimg.org/998w2sb0b/blackops2hack.gif$domain=unknowncheats.me ||poststar.com^*/ad_ ||poststar.com^*/dealwidget.php? ||poststar.com^*/promos/ ||power1035fm.com^*/banners/ ||power977.com/images/banners/ ||powerbot.org^*/ads/ ||powvideo.net/ban/ ||pqarchiver.com^*/utilstextlinksxml.js ||pr0gramm.com/wm/ ||praguepost.com/images/banners/ ||preev.com/ads| ||preev.com/ad| ||prehackshub.com/js/popup-wide.js ||premierleague.com^*/sponsor_ ||preppersmallbiz.com/wp-content/uploads/*/PSB-Support.jpg ||prepperwebsite.com/wp-content/uploads/*-250x250.jpg ||prepperwebsite.com/wp-content/uploads/*/250x250- ||prepperwebsite.com/wp-content/uploads/*/apmgoldmembership250x250.jpg ||prepperwebsite.com/wp-content/uploads/*/DeadwoodStove-PW.gif ||prepperwebsite.com/wp-content/uploads/*/FME-Red-CAP.jpg ||prepperwebsite.com/wp-content/uploads/*/jihad.jpg ||prepperwebsite.com/wp-content/uploads/*/PW-Ad.jpg ||prepperwebsite.com/wp-content/uploads/*/tsepulveda-1.jpg ||prepperwebsite.com/wp-content/uploads/*_250x150.png ||prepperwebsite.com/wp-content/uploads/*_250x250.jpg ||prerollads.ign.com^ ||pressrepublican.com/wallpaper/ ||primenews.com.bd/add/ ||primewire.ag/frame_header.php?$subdocument ||printfriendly.com/a/lijit/ ||prisonplanet.com^*banner ||pro-clockers.com/images/banners/ ||professionalmuscle.com/*banner ||professionalmuscle.com/220x105%20ver2.gif ||professionalmuscle.com/featured-concreter.jpg ||professionalmuscle.com/phil1.jpg ||professionalmuscle.com/PL2.gif ||project-for-sell.com/_google.php ||projectfreetv.ch/adblock/ ||projectorcentral.com/bblaster.cfm?$image ||promo.fileforum.com^ ||propakistani.pk/data/warid_top1.html ||propakistani.pk/data/zong.html ||propakistani.pk/wp-content/*/warid.jpg ||propakistani.pk/wp-content/themes/propakistani/images/776.jpg ||propertyeu.info/peu_storage_banners/ ||proxy-list.org/img/isellsite.gif ||proxy.org/af.html ||proxy.org/ah.html ||proxycape.com/blah.js ||ps3crunch.net/forum/images/gamers/ ||psgroove.com/images/*.jpg| ||ptf.com/fdm_frame_ ||ptf.com/js/fdm_banner.js ||ptf.com/js/ptf_rc_*.js ||ptf.com/js/rc_banner.js ||publichd.eu/images/direct.download.ico ||publichd.eu/images/directdownload.png ||publicityupdate.co.za/temp/banner_ ||publicradio.org^*/banners/ ||publicservice.co.uk^*/spons_ ||pulsetv.com/banner/ ||pumasrugbyunion.com/images/sponsors/ ||punch.cdn.ng^*/wp-banners/ ||punchng.com^*/wp-banners/ ||punksbusted.com/images/ventrilo/ ||punksbusted.com^*/clanwarz-portal.jpg ||pushsquare.com/wp-content/themes/pushsquare/skins/ ||putlocker.is/images/banner ||putlocker.mn^*/download.gif ||putlocker.mn^*/stream-hd.gif ||pv-tech.org/images/footer_logos/ ||pv-tech.org/images/suntech_m2fbblew.png ||q1075.com/images/banners/ ||qatar-tribune.com/images/banners/ ||qiksilver.net^*/banners/ ||qrz.com/pix/*.gif ||qualityhealth.com^*/banner.jsp? ||queenshare.com/popx.js ||quickmeme.com/media/rostile ||quickpwn.com^$subdocument ||quicksilverscreen.com/img/moviesforfree.jpg ||quoteland.com/images/banner2.swf ||race-dezert.com/images/wrap- ||race-dezert.com^*/sponsor- ||racingpost.com/ads/ ||racingpost.com^*_607x30.2.0.gif ||racinguk.com/images/site/foot_ ||rackcdn.com/*Rails_$domain=accesshollywood.com ||rackcdn.com/*skin-$domain=pcgamesn.com ||rad.microsoft.com^ ||rad.msn.com^ ||radio-riverside.co.za/modules/mod_novarp/tmpl/pjmr.swf? ||radio.com/rotatable? ||radio4fm.com/images/background/ ||radio4fm.com/promotion/ ||radio786.co.za/images/banners/ ||radioasiafm.com^*-300x250. ||radiocaroline.co.uk/swf/ACET&ACSP_RadioCaroline_teg.swf ||radioinfo.com/270x270/ ||radioinfo.com^*/575x112- ||radioloyalty.com/newPlayer/loadbanner.html? ||radioreference.com/i/p4/tp/smPortalBanner.gif ||radioreference.com^*_banner_ ||radiotoday.co.uk/a/ ||radiowave.com.na/images/banners/ ||radiowavesforum.com/rw/radioapp.gif ||radiozindagi.com/sponsors/ ||ragezone.com/index.php/$subdocument ||ragezone.com/output.php/ ||rapidfiledownload.com^*/btn-input-download.png ||rapidgamez.com/images/ ||rapidgator.net/images/banners/ ||rapidlibrary.com/baner*.png ||rapidlibrary.com/banner_*.png ||rapidsafe.de/eislogo.gif ||rapidshare.com/promo/$image ||rapidtvnews.com^*BannerAd. ||rapidvideo.org/images/pl_box_rapid.jpg ||rapidvideo.tv/images/pl.jpg ||ratio-magazine.com/images/banners/ ||ravchat.com/img/reversephone.gif ||rawstory.com/givememyrawgfp.php? ||rawstory.com/givememyrawgfpdirect.php? ||rawstory.com/givememyrawjuggler.php ||rawstory.com^*.php?code=bottom ||rawstory.com^*/ads/ ||raysindex.com/wp-content/uploads/*/dolmansept2012flash.swf ||readingeagle.com/lib/dailysponser.js ||realitytvworld.com/burst.js ||realitytvworld.com/includes/rtvw-jscript.js ||reason.org/UserFiles/web-fin1.gif ||red.bayimg.net^ ||reddit.com^*_sponsor.png? ||rediff.com/worldrediff/pix/$subdocument ||rednationonline.ca/Portals/0/derbystar_leaderboard.jpg ||redpepper.org.uk/ad- ||redvase.bravenet.com^ ||reelzchannel.com^*-skin- ||regmender.com^*/banner336x280. ||regnow.img.digitalriver.com/vendor/37587/ud_box$third-party ||rejournal.com/images/banners/ ||rejournal.com/users/blinks/ ||rejournal.com^*/images/homepage/ ||releaselog.net/468.htm ||releaselog.net/uploads2/656d7eca2b5dd8f0fbd4196e4d0a2b40.jpg ||relink.us/js/ibunkerslide.js ||replacementdocs.com^*/popup.js ||retrevo.com/m/google?q= ||retrevo.com^*/pcwframe.jsp? ||reviewcentre.com/cinergy-adv.php ||revisionworld.co.uk/sites/default/files/imce/Double-MPU2-v2.gif ||rfu.com/js/jquery.jcarousel.js ||rghost.ru/download/a/*/banner_download_ ||richardroeper.com/assets/banner/ ||richmedia.yimg.com^ ||riderfans.com/other/ ||rightsidenews.com/images/banners/ ||rislivetv.com/ad*.php ||rlsbb.com/wp-content/uploads/izilol.gif ||rlsbb.com/wp-content/uploads/smoke.jpg ||rockettheme.com/aff/ ||rocksound.tv/images/uploads/*-rocksound-1920x1000_ ||rocktelevision.com^*_banner_ ||rockthebells.net/images/banners/ ||rockthebells.net/images/bot_banner_ ||rocvideo.tv/pu/$subdocument ||rodfile.com/images/esr.gif ||roia.com^ ||rok.com.com/rok-get? ||rollingstone.co.za/images/banners/ ||rom-freaks.net/popup.php ||romhustler.net/square.js ||rootsweb.com/js/o*.js ||roseindia.net^*/banners/ ||rough-polished.com/upload/bx/ ||routerpasswords.com/routers.jpg ||routes-news.com/images/banners/ ||routesonline.com/banner/ ||rpgwatch.com^*/banner/ ||rpt.anchorfree.net^ ||rsbuddy.com/campaign/ ||rss2search.com/delivery/ ||rt.com/banner/ ||rt.com/static/img/banners/ ||rtcc.org/systems/sponsors/ ||rubiconproject.com^$domain=optimized-by.rubiconproject.com ||rugbyweek.com^*/sponsors/ ||runt-of-the-web.com/wrap1.jpg ||russianireland.com/images/banners/ ||s.imwx.com^*/wx-a21-plugthis.js ||s.yimg.com^*/audience/ ||saabsunited.com/wp-content/uploads/*-banner- ||saabsunited.com/wp-content/uploads/*-banner. ||saabsunited.com/wp-content/uploads/*_banner_ ||saabsunited.com/wp-content/uploads/180x460_ ||saabsunited.com/wp-content/uploads/ban- ||saabsunited.com/wp-content/uploads/rbm21.jpg ||saabsunited.com/wp-content/uploads/REALCAR-SAABSUNITED-5SEC.gif ||saabsunited.com/wp-content/uploads/USACANADA.jpg ||saabsunited.com/wp-content/uploads/werbung- ||sacbee.com/static/dealsaver/ ||sacommercialpropnews.co.za/files/banners/ ||saf.org/wp-content/uploads/*/theGunMagbanner.png ||saf.org/wp-content/uploads/*/women_guns192x50.png ||safelinks.eu/open.js ||sagoodnews.co.za/templates/ubuntu-deals/ ||salfordonline.com/sponsors/ ||salfordonline.com/sponsors2/ ||sameip.org/images/froghost.gif ||samoaobserver.ws^*/banner/ ||samoatimes.co.nz^*/banner468x60/ ||sapeople.com/wp-content/uploads/wp-banners/ ||sarasotatalkradio.com^*-200x200.jpg ||sarugbymag.co.za^*-wallpaper2. ||sat24.com/bannerdetails.aspx? ||satelliteguys.us/burst_ ||satelliteguys.us/pulsepoint_ ||satellites.co.uk/images/sponsors/ ||satnews.com/images/MITEQ_sky.jpg ||satnews.com/images/MSMPromoSubSky.jpg ||satopsites.com^*/banners/ ||savefrom.net/img/a1d/ ||saveondish.com/banner2.jpg ||saveondish.com/banner3.jpg ||sawlive.tv/ad ||sayellow.com/Clients/Banners/ ||saysuncle.com^*ad.jpg ||sbnation.com/campaigns_images/ ||scenicreflections.com/dhtmlpopup/ ||sceper.eu/wp-content/banners.min.js ||schenkelklopfer.org^$domain=4fuckr.com ||scientopia.org/public_html/clr_lympholyte_banner.gif ||scmagazine.com.au/Utils/SkinCSS.ashx?skinID= ||scoop.co.nz/xl?c$subdocument ||scoot.co.uk/delivery.php ||screen4u.net/templates/banner.html ||screenafrica.com/jquery.jcarousel.min.js ||screencrave.com/show/ ||screenlist.ru/dodopo.js ||screenlist.ru/porevo.js ||scribol.com/broadspring.js ||scriptcopy.com/tpl/phplb/search.jpg ||scriptmafia.org/banner.gif ||search-torrent.com/images/videox/ ||search.ch/acs/ ||search.ch/htmlbanner.html ||search.triadcareers.news-record.com/jobs/search/results?*&isfeatured=y& ||search.triadcars.news-record.com/autos/widgets/featuredautos.php ||searchenginejournal.com^*-takeover- ||searchenginejournal.com^*/sej-bg-takeover/ ||searchenginejournal.com^*/sponsored- ||searchignited.com^ ||searchtempest.com/clhimages/aocbanner.jpg ||seatguru.com/deals? ||seclists.org/shared/images/p/$image ||sectools.org/shared/images/p/$image ||secureupload.eu/gfx/dlbtn.png ||secureupload.eu/gfx/freedl.png ||secureupload.eu/js/poad.js ||securitymattersmag.com/scripts/popup.js ||securitywonks.net/promotions/ ||sedo.cachefly.net^$domain=~sedoparking.com ||sedoparking.com/images/js_preloader.gif ||sedoparking.com/jspartner/ ||sedoparking.com/registrar/dopark.js ||seedboxes.cc/images/seedad.jpg ||seeingwithsound.com/noad.gif ||segmentnext.com/javascripts/interstitial.client.js ||sendspace.com/defaults/framer.html?z= ||sendspace.com/images/shutter.png ||sendspace.com^*?zone= ||sensongs.com/nfls/ ||serial.sw.cracks.me.uk/img/logo.gif ||serials.ws^*/logo.gif ||serialzz.us/ad.js ||sermonaudio.com/images/sponsors/ ||sexmummy.com/avnadsbanner. ||sfbaytimes.com/img-cont/banners ||sfltimes.com/images/banners/ ||sfx.ms/AppInsights-$script ||shadowpool.info/images/banner- ||shanghaidaily.com/include/bettertraffic.asp ||shanghaiexpat.com^*/wallpaper_ ||share-links.biz/get/cmm/ ||share-links.biz^*/hisp.gif ||share-links.biz^*/hs.gif ||sharebeast.com/topbar.js ||sharephile.com/js/pw.js ||sharesix.com/a/images/watch-bnr.gif ||sharetera.com/images/icon_download.png ||sharetera.com/promo.php? ||sharkscope.com/images/verts/$image ||sherdog.com/index/load-banner? ||shodanhq.com/images/s/acehackware-obscured.jpg ||shop.com/cc.class/dfp? ||shop.sportsmole.co.uk/pages/deeplink/ ||shopping.stylelist.com/widget? ||shoppingpartners2.futurenet.com^ ||shops.tgdaily.com^*&widget= ||shopwiki.com/banner_iframe/ ||shortcuts.search.yahoo.com^*&callback=yahoo.shortcuts.utils.setdittoadcontents& ||shortlist.com/resource/cache/*skin ||shortlist.com^*-takeover. ||shoutmeloud.com^*/hostgator- ||show-links.tv/layer.php ||showbusinessweekly.com/imgs/hed/ ||showstreet.com/banner. ||shroomery.org/bimg/ ||shroomery.org/bnr/ ||shroomery.org/images/shroomery.please.png ||shroomery.org/images/www.shroomery.org.please.png ||shtfplan.com/images/banners/ ||siberiantimes.com/upload/banners/ ||sicilianelmondo.com/banner/ ||sickipedia.org/static/images/banners/ ||sidereel.com^*/featured_logo/ ||sify.com/images/games/gadvt/ ||sify.com^*/gads_ ||sigalert.com/getunit.asp?$subdocument ||siliconrepublic.com/fs/img/partners/ ||silverdoctors.com^*/Silver-Shield-2015.jpg ||sisters-magazine.com^*/Banners/ ||sitedata.info/doctor/ ||sitesfrog.com/images/banner/ ||siteslike.com/images/celeb ||siteslike.com/js/fpa.js ||sk-gaming.com/image/acersocialw.gif ||sk-gaming.com/image/pts/ ||sk-gaming.com/www/skdelivery/ ||skynews.com.au/elements/img/sponsor/ ||skysports.com/images/skybet.png ||skyvalleychronicle.com/999/images/ban ||slacker.com/wsv1/getspot/?$object-subrequest ||slacker.com^*/adnetworks.swf ||slacker.com^*/ads.js ||slacker.com^*/getspot/?spotid= ||slashgear.com/static/banners/ ||slayradio.org/images/c64audio.com.gif ||slickvid.com/js/fun.js ||slickvid.com/js/fun2.js ||slyck.com/pics/*304x83_ ||smartcompany.com.au/images/stories/sponsored-posts/ ||smartearningsecrets.com^*/FameThemes.png ||smartmoney.net^*-sponsor- ||smartname.com/scripts/google_afd_v2.js ||smashingapps.com/banner/ ||smh.com.au/compareandsave/ ||smh.com.au/images/promo/ ||smile904.fm/images/banners/ ||smn-news.com/images/banners/ ||smn-news.com/images/flash/ ||smoothjazznetwork.com/images/buyicon.jpg ||smotrisport.com/ads/ ||smwcentral.net/html/$image ||snimg.com/image/sponsors/ ||snopes.com/common/include/$subdocument ||snopes.com^*/casalebanner.asp ||snopes.com^*/casalebox.asp ||snopes.com^*/casalesky.asp ||snopes.com^*/tribalbox.asp ||soccerlens.com/files1/ ||soccervista.com/bahforgif.gif ||soccervista.com/bonus.html ||soccervista.com/sporting.gif ||soccerway.com/buttons/120x90_ ||soccerway.com/img/betting/ ||socialstreamingplayer.crystalmedianetworks.com//async/banner/ ||sockshare.com/*.php?embed*type=$subdocument ||sockshare.com/moo.php ||sockshare.com/rev/ ||sockshare.com^*.php?*title$subdocument ||sockshare.com^*_728.php ||socsa.org.za/images/banners/ ||softcab.com/google.php? ||softonic.com/specials_leaderboard/ ||softpedia-static.com/images/*.jpg?v ||softpedia-static.com/images/*.png?v ||softpedia-static.com/images/aff/ ||softpedia-static.com/images/afg/ ||softpedia-static.com/images/afh/$domain=softpedia.com ||soldierx.com/system/files/images/sx-mini-1.jpg ||solomonstarnews.com/images/banners/ ||solvater.com/images/hd.jpg ||someecards.com^*/images/skin/ ||songs.pk/textlinks/ ||songspk.link/textlinks/ ||songspk.name/fidelity.html$domain=songs.pk|songspk.name ||songspk.name/imagepk.gif ||songspk.name/textlinks/ ||sootoday.com/uploads/banners/ ||sorcerers.net/images/aff/ ||soundcloud.com/audio-ad? ||soundcloud.com/promoted/ ||soundspheremag.com/images/banners/ ||soundtracklyrics.net^*_az.js ||sourcefed.com/wp-content/uploads/*/netflix4.jpg ||sourceforge.net/images/ban/ ||southafricab2b.co.za/banners/ ||sowetanlive.co.za/banners/ ||space.com/promo/ ||spaceweather.com/abdfeeter/$image ||spartoo.eu/footer_tag_iframe_ ||spcontentcdn.net^$domain=sporcle.com ||speedtest.net/flash/59rvvrpc-$object-subrequest ||speedtest.net/flash/60speedify1-$object-subrequest ||speedtv.com.edgesuite.net/img/monthly/takeovers/ ||speedtv.com/js/interstitial.js ||speedtv.com^*/tissot-logo.png ||speedvid.net/ad.htm ||speedvideo.net/img/playerFk.gif ||speroforum.com/images/sponsor_ ||spicegrenada.com/images/banners/ ||sponsors.s2ki.com^ ||sponsors.webosroundup.com^ ||sporcle.com/adn/yak.php? ||sportcategory.com/ads/ ||spotflux.com/service/partner.php ||spreaker.net/spots/ ||sptimes.ru/clients/banners_ ||spycss.com/images/hostgator.gif ||spyw.com^$domain=uploadlw.com ||squadedit.com/img/peanuts/ ||srv.thespacereporter.com^ ||ssl-images-amazon.com/images/*/browser-scripts/da- ||st701.com/stomp/banners/ ||stad.com/googlefoot2.php? ||stagnitomedia.com/view-banner- ||standard.net/sites/default/files/images/wallpapers/ ||standardmedia.co.ke/flash/expandable.swf ||star883.org^*/sponsors. ||startxchange.com/bnr.php ||static-economist.com^*/timekeeper-by-rolex-medium.png ||static.btrd.net/*/interstitial.js$domain=businessweek.com ||static.ec.own3d.tv/lr/$object-subrequest ||static.hd-trailers.net/js/javascript_*.js| ||static.nfl.com^*-background- ||static.plista.com^$script,domain=wg-gesucht.de ||staticneo.com/neoassets/iframes/leaderboard_bottom. ||staticworld.net/images/*_pcwskin_ ||steambuy.com/steambuy.gif ||sternfannetwork.com/forum/images/banners/ ||steroid.com/banner/ ||steroid.com/dsoct09.swf ||sticker.yadro.ru/ad/ ||stjohntradewindsnews.com/images/banners/ ||stltoday.com^*_sponsor.gif ||stlyrics.com^*_az.js ||stlyrics.com^*_st.js ||stockhouse.com^*-300x75.gif ||stopforumspam.com/img/snelserver.swf ||stopstream.com/ads/ ||storewidget.pcauthority.com.au^ ||strategypage.com^*_banner ||stream.heavenmedia.net^ ||stream2watch.me/600pick.png ||stream2watch.me/900rev.html ||stream2watch.me/900yahoo.html ||stream2watch.me/_$subdocument ||stream2watch.me/ad.html ||stream2watch.me/ad10.html ||stream2watch.me/chat1.html ||stream2watch.me/eadb.php ||stream2watch.me/eadt.php ||stream2watch.me/ed ||stream2watch.me/images/hd1.png ||stream2watch.me/Los_Br.png ||stream2watch.me/yield.html ||streamcloud.eu/deliver.php ||student-jobs.co.uk/banner. ||stuff.co.nz/1319769787/395/5871395.jpg ||stuff.co.nz/1361239022/107/8323107.jpg ||stuff.co.nz/clientdev/production/iframes/ ||stuff.co.nz/stuff/*banner ||stuff.co.nz/stuff/misc/flying-flowers/ ||stuff.co.nz/stuff/tom/mags-widget/ ||stuff.co.nz/stuff/widgets/lifedirect/ ||stuff.priceme.co.nz^$domain=stuff.co.nz ||stuff.tv/client/skinning/ ||stv.tv/img/player/stvplayer-sponsorstrip- ||subs4free.com^*/wh4_s4f_$script ||succeed.co.za^*/banner_ ||sulekha.com^*/bannerhelper.html ||sulekha.com^*/sulekhabanner.aspx ||sun-fm.com/resources/creative/ ||sunriseradio.com/js/rbanners.js ||sunshineradio.ie/images/banners/ ||suntimes.com^*/banners/ ||superbike-news.co.uk/absolutebm/banners/ ||supermarket.co.za/images/advetising/ ||supermonitoring.com/images/banners/ ||superplatyna.com/automater.swf ||surfthechannel.com/promo/ ||swagmp3.com/cdn-cgi/pe/ ||swampbuggy.com/media/images/banners/ ||swedishwire.com/images/banners/ ||sweepsadvantage.com/336x230-2.php ||swiftco.net/banner/ ||swimnews.com^*/banner_ ||swimnewslibrary.com^*_960x120.jpg ||swoknews.com/images/banners/ ||sxc.hu/img/banner ||sydneyolympicfc.com/admin/media_manager/media/mm_magic_display/$image ||systemexplorer.net/sessg.php ||sythe.org/bnrs/ ||sythe.org/clientscript/agold.png ||tabla.com.sg/SIA.jpg ||tabloidmedia.co.za/images/signs2.swf ||taipeitimes.com/js/gad.js? ||taiwannews.com.tw/etn/images/banner_ ||take40.com/css/takeover.css ||take40.com/images/takeover/ ||talkers.com/imagebase/ ||talkers.com/images/banners/ ||talkgold.com/bans/ ||talkphotography.co.uk/images/externallogos/banners/ ||talkradioeurope.com/images/banners/ ||talkradioeurope.net/images/banners/ ||talksport.co.uk^*/ts_takeover/ ||tampermonkey.net/bner/ ||tampermonkey.net^*.*.$subdocument ||tanzanite.infomine.com^ ||targetedinfo.com^ ||targetedtopic.com^ ||tastro.org/x/ads*.php ||tbs.com^*/ad_policy.xml$object-subrequest,domain=tbs.com ||tdfimg.com/go/*.html ||teamfourstar.com/img/918thefan.jpg ||techexams.net/banners/ ||techhive.com/ads/ ||technewsdaily.com/crime-stats/local_crime_stats.php ||technewsworld.com/images/sda/ ||technomag.co.zw^*/TakeOverCampaign. ||techpowerup.com/images/bnnrs/ ||techradar.com^*/img/*_takeover_ ||techsonia.com/cdn-cgi/pe/bag2?r[]=*.content.ad ||techsupportforum.com^*/banners/ ||techtarget.com^*/leaderboard.html ||techtree.com^*/jquery.catfish.js ||teesoft.info/images/uniblue.png ||teesupport.com/wp-content/themes/ts-blog/images/cp- ||tehrantimes.com/images/banners/ ||telecomtiger.com^*_250x250_ ||telecomtiger.com^*_640x480_ ||telegraph.co.uk/international/$subdocument ||telegraph.co.uk/sponsored/ ||telegraphindia.com^*/banners/ ||telegraphindia.com^*/hoabanner. ||templatesbox.com^*/banners/ ||ten-tenths.com/sidebar.html ||tenmanga.com/files/js/manga_$subdocument ||tenmanga.com/files/js/site_skin.js ||tennischannel.com/prud.jpg ||tennischannel.com/tc-button-gif.gif ||tennisworldusa.org/banners/ ||tentonhammer.com^*/takeovers/ ||terafile.co/i/banners/ ||testseek.com/price_pricegrabber_ ||textpattern.com/images/117.gif ||thaivisa.com/promotions/banners/ ||the-numbers.com^*/allposters/ ||theactivetimes.net^*/featured_partners/ ||theafricachannel.com^*/promos/ ||theaquarian.com^*/banners/ ||theartnewspaper.com/aads/ ||theasiantoday.com/image/banners/ ||theattractionforums.com/images/rbsbanners/ ||thebay.co.uk/banners/ ||thebeat99.com/cmsadmin/banner/ ||theblaze.com^*-background- ||theblaze.com^*-background2- ||theblaze.com^*-backgroundwide- ||theblaze.com^*-interstitial- ||thebull.com.au/admin/uploads/banners/ ||thebulls.co.za^*/sponsors/ ||theburningplatform.com/wp-content/uploads/*_180x150.gif ||thebusinessdesk.com/assets/_files/banners/ ||thecatholicuniverse.com^*-ad. ||thecatholicuniverse.com^*-advert- ||thecatholicuniverse.com^*-banner- ||thecenturion.co.za^*/banners/ ||thecharlottepost.com/cache/sql/fba/ ||thechive.files.wordpress.com^*-wallpaper- ||thecitizen.co.tz^*/banners/ ||thecnj.com/images/hotel-banner.jpg ||thecorrsmisc.com/10feet_banner.gif ||thecorrsmisc.com/brokenthread.jpg ||thecorrsmisc.com/msb_banner.jpg ||thecsuite.co.uk^*/banners/ ||thedailyherald.com/images/banners/ ||thedailymash.co.uk/templates/mashtastic/gutters/ ||thedailymeal.com^*_sponsoredby.png ||thedailymeal.net^*/featured_partners/ ||thedailypaul.com/images/amzn- ||thedailysheeple.com/images/banners/ ||thedailystar.net^*/400-x-120-pixel.jpg ||thedailystar.net^*/Animation-200-X-30.gif ||thedailystar.net^*/aritel-logo.jpg ||thedailystar.net^*/scbbd.gif ||theday.com/assets/images/sponsorlogos/ ||thedomainstat.com/filemanager/userfiles/banners/ ||theedinburghreporter.co.uk/hmbanner/ ||theenglishgarden.co.uk^*/bannerImage. ||thefile.me^*.php?*zoneid ||thefrontierpost.com/media/banner/ ||thehealthcareblog.com/files/*/American-Resident-Project-Logo- ||thehealthcareblog.com/files/*/athena-300.jpg ||thehealthcareblog.com/files/*/THCB-Validic-jpg-opt.jpg ||thehighstreetweb.com^*/banners/ ||thehindu.com/multimedia/*/sivananda_sponsorch_ ||theispguide.com/premiumisp.html ||theispguide.com/topbanner.asp? ||thejesperbay.com^ ||thejointblog.com/wp-content/uploads/*-235x ||thejointblog.com^*/dablab.gif ||thejuice.co.za/wp-content/plugins/wp-plugin-spree-tv/ ||thelakewoodscoop.com^*banner ||theleader.info/banner ||theliberianjournal.com/flash/banner ||thelocal.com/scripts/fancybox/ ||thelodownny.com/leslog/ads/ ||thelyricarchive.com/new/view/ ||themag.co.uk/assets/BV200x90TOPBANNER.png ||themidweeksun.co.bw/images/banners/ ||theminiforum.co.uk/images/banners/ ||themis-media.com/media/global/images/cskins/ ||themis.yahoo.com^ ||themiscellany.org/images/banners/ ||themittani.com/sites/*-skin ||thenassauguardian.com/images/banners/ ||thenationonlineng.net^*/banners/ ||thenewage.co.za/Image/kingprice.gif ||thenewjournalandguide.com/images/banners/ ||thenextweb.com/wp-content/plugins/tnw-siteskin/mobileys/ ||thenonleaguefootballpaper.com^*-140x300- ||thenonleaguefootballpaper.com^*/140x140_ ||thenonleaguefootballpaper.com^*/ADIDAS_11PRO_WHITEOUT.jpg ||thenonleaguefootballpaper.com^*/Budweiser.jpg ||thenonleaguefootballpaper.com^*/image-non-league.jpeg ||thenonleaguefootballpaper.com^*/J4K-new-range-pictures.jpg ||thenonleaguefootballpaper.com^*/Lovell-Soccer.jpg ||theoldie.co.uk/Banners/ ||theolympian.com/static/images/weathersponsor/ ||theonion.com/ads/ ||theorganicprepper.ca/images/banners/ ||thepaper24-7.com/SiteImages/Banner/ ||thepaper24-7.com/SiteImages/Tile/ ||thepeak.fm/images/banners/ ||thepeninsulaqatar.com^*/banners/ ||thephuketnews.com/photo/banner/ ||thepiratebay.se^*/poptest.js ||theplanetweekly.com/images/banners/ ||theportugalnews.com/uploads/banner/ ||thepreparednessreview.com/wp-content/uploads/*/250x125- ||thepreparednessreview.com/wp-content/uploads/*_175x175.jpg ||thepreparednessreview.com/wp-content/uploads/*_185x185.jpg ||theradiomagazine.co.uk/banners/ ||theradiomagazine.co.uk/images/bionics.jpg ||therugbyforum.com/trf-images/sponsors/ ||thesentinel.com^*/banners/ ||thesource.com/magicshave/ ||thespiritsbusiness.com^*/Banner150 ||thessdreview.com/wp-content/uploads/*/930x64_ ||thessdreview.com^*-bg.jpg ||thessdreview.com^*/owc-full-banner.jpg ||thessdreview.com^*/owc-new-gif1.gif ||thestandard.com.hk/banners/ ||thestandard.com.hk/rotate_ ||thestkittsnevisobserver.com/images/banners/ ||thesundaily.my/sites/default/files/twinskyscrapers ||thesurvivalistblog.net^*-banner- ||thesweetscience.com/images/banners/ ||theticketmiami.com/Pics/listenlive/*-Left.jpg ||theticketmiami.com/Pics/listenlive/*-Right.jpg ||thetimes.co.uk/public/encounters/ ||thetvdb.com/images/frugal.gif ||thetvdb.com/images/jriver_banner.png ||thevideo.me/cgi-bin/get_creatives.cgi? ||thevideo.me/creatives/ ||thewb.com/thewb/swf/tmz-adblock/ ||thewindowsclub.com^*/banner_ ||theyeshivaworld.com/yw/ ||thinkbroadband.com/uploads/banners/ ||thinkingwithportals.com/images/*-skyscraper. ||thinkingwithportals.com^*-skyscraper.swf ||thirdage.com^*_banner.php ||thisisanfield.com^*takeover ||thunder106.com//wp-content/banners/ ||ticketnetwork.com/images/affiliates/ ||tigerdroppings.com^*&adcode= ||time4tv.com/tlv. ||timeinc.net/*/i/oba-compliance.png ||timeinc.net^*/recirc.js ||times-herald.com/pubfiles/ ||times.co.sz/files/banners/ ||timesnow.tv/googlehome.cms ||timesofoman.com/FrontInc/top.aspx ||timesofoman.com/siteImages/MyBannerImages/ ||timesofoman.com^*/banner/ ||timestalks.com/images/sponsor- ||tindleradio.net/banners/ ||tinychat.com/channel?frame=true&$subdocument,domain=tinypaste.com ||tinypaste.com/public/images/480.png ||tinyurl.com/firefox_banner_ ||titanshare.to/images/buttons/download.gif ||titantorrent.to^*/buttons/download.gif ||titantv.com/gravity.ashx ||tmcs.net^ ||tmz.vo.llnwd.net^*/images/*skin ||tmz.vo.llnwd.net^*/sponsorship/$domain=tmz.com ||tnij.org/rotator ||tny.cz/oo/ ||tom.itv.com^ ||tomshardware.com/indexAjax.php?ctrl=ajax_pricegrabber$xmlhttprequest ||tomshardware.com/price/widget/?$xmlhttprequest ||toolslib.net/assets/img/a_dvt/ ||toomuchnews.com/dropin/ ||toonova.com/images/site/front/xgift- ||toonzone.net^*/placements.php? ||topalternate.com/assets/sponsored_links- ||topfriv.com/popup.js ||topix.com/ajax/krillion/ ||toptenreviews.com/flash/ ||torrent-finder.info/cont.html ||torrent-finder.info/cont.php ||torrent.cd/images/banner- ||torrent.cd/images/big_use.gif ||torrent.cd/images/main_big_msoft.jpg ||torrent.cd/images/sp/ ||torrentbit.net/images/1click/button-long.png ||torrentbox.sx/img/download_direct.png ||torrentcrazy.com/img/wx.png ||torrentcrazy.com/pnd.js ||torrenteditor.com/img/graphical-network-monitor.gif ||torrentfreak.com/images/vuze.png ||torrentfunk.com/affprofslider.js ||torrentfusion.com/FastDownload.html ||torrentproject.org/out/ ||torrentroom.com/js/torrents.js ||torrents.net/btguard.gif ||torrents.net/wiget.js ||torrentv.org/images/tsdd.jpg ||torrentv.org/images/tsdls.jpg ||torrentz.*/mgid/ ||totalcmd.pl/img/billboard_ ||totalcmd.pl/img/nucom. ||totalcmd.pl/img/olszak. ||totalguitar.net/images/*_125X125.jpg ||totalguitar.net/images/tgMagazineBanner.gif ||toucharcade.com/wp-content/themes/*_background_*.jpg ||toucharcade.com/wp-content/themes/skin_zero/images/skin_assets/main_skin.jpg ||toucharcade.com/wp-content/uploads/skins/ ||townhall.com^*/ads/ ||toynews-online.biz/media/banners/ ||toynewsi.com/a/ ||toywiz.com/lower-caption-global.html ||tpb.piraten.lu/static/img/bar.gif ||tpucdn.com/images/b/$domain=techpowerup.com ||tracking.hostgator.com^ ||trackitdown.net/skins/*_campaign/ ||tracksat.com^*/banners/ ||tradewinds.vi/images/banners/ ||trgoals.es/adk.html ||tribune.com.ng/images/banners/ ||tribune242.com/pubfiles/ ||tripadvisor.*/adp/adp-$subdocument ||tripadvisor.com/adp/ ||tripadvisor.com^*/skyscraper.jpg ||truck1.eu/_BANNERS_/ ||trucknetuk.com^*/sponsors/ ||trucktrend.com^*_160x200_ ||trustedreviews.com/mobile/widgets/html/promoted-phones? ||trutv.com/includes/mods/iframes/mgid-blog.php ||tsatic-cdn.net/takeovers/$image ||tsdmemphis.com/images/banners/ ||tsn.ca^*_sponsor. ||tubehome.com/imgs/undressme ||tubeplus.me/resources/js/codec.js ||tullahomanews.com/news/banners/ ||tullahomanews.com/news/tn-popup.js ||tune.pk/plugins/cb_tunepk/ads/ ||turbobit.net/js/acontrol.js? ||turbobit.net/oexktl/muzebra_ ||turbobit.net/pics/7z1xla23ay_ ||turboimagehost.com/300*.html^ ||turboimagehost.com/728*.html^ ||turboimagehost.com/p.js ||turboyourpc.com/images/affiliates/ ||turnstylenews.com^*/sponsors.png ||tusfiles.net/i/dll.png ||tusfiles.net/images/tusfilesb.gif ||tuspics.net/onlyPopupOnce.js ||tv4chan.com/iframes/ ||tvbrowser.org/logo_df_tvsponsor_ ||tvcatchup.com/wowee/ ||tvducky.com/imgs/graboid. ||tvguide.com^*/ecommerce/ ||tvsubtitles.net/banners/ ||tweaktown.com/cms/includes/i*.php ||twentyfour7football.com^*/gpprint.jpg ||twitch.tv/ad/*=preroll ||twitch.tv/widgets/live_embed_player.swf$domain=gelbooru.com ||twnmm.com^*/sponsored_logo. ||txfm.ie^*/amazon-16x16.png ||txfm.ie^*/itunes-16x16.png ||u.tv/images/misc/progressive.png ||u.tv/images/sponsors/ ||u.tv/utvplayer/jwplayer/ova.swf ||ua.badongo.com^ ||uberhumor.com/*btf.html$subdocument ||uberhumor.com/iframe$subdocument ||ubuntugeek.com/images/dnsstock.png ||ubuntugeek.com/images/od.jpg ||ubuntugeek.com/images/ubuntu1.png ||ufonts.com/gfx/uFonts_Banner5.png ||ugo.com/takeover/ ||uimserv.net^ ||ujfm.co.za/images/banners/ ||uk-mkivs.net/uploads/banners/ ||ukbusinessforums.co.uk/adblock/ ||ukcampsite.co.uk/banners/ ||ukcast.co/pubfit.php ||ukcast.co/rbt728.php ||ukfindit.com/images/*_125x125.gif ||ukfindit.com/wipedebtclean.png ||ukradioplayer.kerrangradio.co.uk^*/icon_amazon.png ||ukradioplayer.kerrangradio.co.uk^*/icon_apple.png ||ultimate-guitar.com/_img/bgd/bgd_main_ ||ultimate-guitar.com/_img/promo/takeovers/ ||ultimate-guitar.com/bgd/main_$image ||ultimate-guitar.com^*/takeover/ ||ultimatehandyman.co.uk/ban.txt ||ultimatehandyman.org/bh1.gif ||ultimatewindowssecurity.com/images/banner80x490_WSUS_FreeTool.jpg ||ultimatewindowssecurity.com/images/patchzone-resource-80x490.jpg ||ultimatewindowssecurity.com/images/spale.swf ||ultimatewindowssecurity.com/securitylog/encyclopedia/images/allpartners.swf ||umbrelladetective.com/uploaded_files/banners/ ||unawave.de/medien/a/w-ama-$image ||unawave.de/medien/ama/$image ||unawave.de/medien/wbwso-$image ||unawave.de/templates/unawave/a/$image ||unblockedpiratebay.com/external/$image ||unblockt.com/scrape_if.php ||uncoached.com/smallpics/ashley ||unicast.ign.com^ ||unicast.msn.com^ ||uniindia.com/eng/bannerbottom.php ||uniindia.com/eng/bannerheader.php ||uniindia.com/eng/bannerrightside.php ||uniindia.com/eng/banners/ ||uniindia.com/eng/bannertopright.php ||uniindia.net/eng/banners/ ||uniquefm.gm/images/banners/ ||universalhub.com/bban/ ||upload.ee/image/*/B_descarga_tipo12.gif ||uploadbaz.com^*-728-$object ||uploadcore.com/images/*-Lad.jpg ||uploadcore.com/images/*-mad.jpg ||uploadcore.com/images/*-Rad.png ||uploaded.net/js2/downloadam.js ||uploaded.to/img/e/ad/ ||uploading.com/static/banners/ ||uploadlw.com/js/cash.js ||uploadlw.com^*/download-now ||uploadlw.com^*/download_button.gif ||uptobox.com/ayl.js ||uptobox.com/images/download.png ||uptobox.com/images/downloaden.gif ||urbanchristiannews.com/ucn/sidebar- ||urbanfonts.com/images/fonts_com/ ||urbanvelo.org/sidebarbanner/ ||urethanes-technology-international.com^*/banners/ ||urlcash.net/newpop.js ||urlcash.net/random*.php ||urlcash.org/abp/ ||urlcash.org/banners/ ||urlcash.org/newpop.js ||urlgone.com^*/banners/ ||usanetwork.com/_js/ad.js ||usatoday.net^*/lb-agate.png ||usatodayhss.com/images/*skin ||uschess.org/images/banners/ ||usenet-crawler.com/astraweb.png ||usenet-crawler.com/purevpn.png ||usforacle.com^*-300x250.gif ||ustatik.com/_img/promo/takeovers/$domain=ultimate-guitar.com ||ustatik.com/_img/promo/takeovers_$domain=ultimate-guitar.com ||ustream.tv/takeover/ ||uvnc.com/img/housecall. ||val.fm/images/banners/ ||valleyplanet.com/images/banners/ ||vanityfair.com/custom/ebook-ad-bookbiz ||vasco.co.za/images/banners/ ||vault.starproperty.my/widget/ ||vcdq.com/tag.html ||vcdq.com^*/ad.html ||vehix.com/tags/default.imu?$subdocument ||verdict.abc.go.com^ ||verizon.com/ads/ ||verzend.be/images/download.png ||verzing.com/popup ||vfs-uk-in.com/images/webbanner- ||vhd.me/custom/interstitial ||viadeo.com/pub/ ||viamichelin.co.uk/htm/cmn/afs*.htm? ||viator.com/analytics/percent_mobile_hash.js ||vidbull.com/tags/vidbull_bnr.png ||vidds.net/pads*.js ||video-cdn.abcnews.com/ad_$object-subrequest ||video-cdn.abcnews.com^*_ad_$object-subrequest,domain=go.com ||video.abc.com^*/ads/ ||video.thestaticvube.com/video/*.mp4$object-subrequest,domain=vube.com ||video44.net/gogo/a_d_s. ||video44.net/gogo/qc.js ||video44.net/gogo/yume-h.swf$object-subrequest ||videobam.com/images/banners/ ||videobam.com/this-pays-for-bandwidth/ ||videobash.com/images/playboy/ ||videobull.com/wp-content/themes/*/watch-now.jpg ||videobull.com^*/amazon_ico.png ||videobull.to/wp-content/themes/videozoom/images/gotowatchnow.png ||videobull.to/wp-content/themes/videozoom/images/stream-hd-button.gif ||videodorm.org/player/yume-h.swf$object-subrequest ||videodownloadtoolbar.com/fancybox/ ||videogamer.com/videogamer*/skins/ ||videogamer.com^*/css/skins/$stylesheet ||videogamesblogger.com/takeover.html ||videogamesblogger.com^*/scripts/takeover.js ||videolan.org/images/events/animated_packliberte.gif ||videopediaworld.com/nuevo/plugins/midroll. ||videos.com/click? ||videos.mediaite.com/decor/live/white_alpha_60. ||videositeprofits.com^*/banner.jpg ||videowood.tv/ads ||videowood.tv/assets/js/popup.js ||videowood.tv/pop2 ||vidhog.com/images/download_banner_ ||vidspot.net/player/ova-jw.swf$object-subrequest ||vidspot.net^$subdocument,domain=vidspot.net ||vidspot.net^*/pu.js ||vidvib.com/vidvibpopa. ||vidvib.com/vidvibpopb. ||viewdocsonline.com/images/banners/ ||villagevoice.com/img/VDotDFallback-large.gif ||vinaora.com/xmedia/hosting/ ||vipbox.co/js/bn.js ||vipbox.co^*/pu.js ||vipbox.tv/js/layer- ||vipbox.tv/js/layer.js ||vipi.tv/ad.php ||vipleague.se/js/vip.js ||virtual-hideout.net/banner ||virtualtourist.com/adp/ ||vistandpoint.com/images/banners/ ||vitalfootball.co.uk/app-interstitial/ ||vitalfootball.co.uk^*/partners/ ||vnbitcoin.org/140_350.jpg ||vnbitcoin.org/gawminers.png ||vodlocker.com/images/acenter.png ||vodo.net/static/images/promotion/utorrent_plus_buy.png ||vogue.in/node/*?section= ||voicescalgary.com/images/leaderBoards/ ||voicescalgary.com/images/stories/banners/ ||voicesedmonton.com/images/leaderBoards/ ||voicesedmonton.com/images/stories/banners/ ||voicesottawa.com/images/leaderBoards/ ||voicesottawa.com/images/stories/banners/ ||voicestoronto.com/images/leaderBoards/ ||voicestoronto.com/images/stories/banners/ ||voicesvancouver.com/images/leaderBoards/ ||voicesvancouver.com/images/stories/banners/ ||vondroid.com/site-img/*-adv-ex- ||vonradio.com/grfx/banners/ ||vortez.co.uk^*120x600.swf ||vortez.co.uk^*skyscraper.jpg ||vosizneias.com/perms/ ||vpsboard.com/display/ ||w.homes.yahoo.net^ ||waamradio.com/images/sponsors/ ||wadldetroit.com/images/banners/ ||wallpaper.com/themes/takeovers/$image ||walshfreedom.com^*-300x250. ||walshfreedom.com^*/liberty-luxury.png ||wambacdn.net/images/upload/adv/$domain=mamba.ru ||wantedinmilan.com/images/banner/ ||wantitall.co.za/images/banners/ ||waoanime.tv/playerimg.jpg ||wardsauto.com^*/pm_doubleclick/ ||warriorforum.com/vbppb/ ||washingtonpost.com/wp-srv/javascript/piggy-back-on-ads.js ||washpost.com^*/cmag_sponsor3.php? ||washtimes.com/static/images/SelectAutoWeather_v2.gif ||watchcartoononline.com^*/530x90. ||watchfreemovies.ch/js/lmst.js ||watchop.com/player/watchonepiece-gao-gamebox.swf ||watchseries.eu/images/affiliate_buzz.gif ||watchseries.eu/images/download.png ||watchseries.eu/js/csspopup.js ||watchuseek.com/flashwatchwus.swf ||watchuseek.com/media/*-banner- ||watchuseek.com/media/*_250x250 ||watchuseek.com/media/1900x220_ ||watchuseek.com/media/banner_ ||watchuseek.com/media/clerc-final.jpg ||watchuseek.com/media/longines_legenddiver.gif ||watchuseek.com/media/wus-image.jpg ||watchuseek.com/site/forabar/zixenflashwatch.swf ||waterford-today.ie^*/banners/ ||wavelengthcalculator.com/banner ||way2sms.com/w2sv5/js/fo_ ||wbal.com/absolutebm/banners/ ||wbgo.org^*/banners/ ||wbj.pl/im/partners.gif ||wcbm.com/includes/clientgraphics/ ||wctk.com/banner_rotator.php ||wdwinfo.com/js/swap.js ||we7.com/images/yahoo/ ||wealthycashmagnet.com/upload/banners/ ||wearetennis.com/img/common/bnp-logo- ||wearetennis.com/img/common/bnp-logo.png ||wearetennis.com/img/common/logo_bnp_ ||weather365.net/images/banners/ ||weatherbug.com^*/ova-jw.swf$object-subrequest ||weatheroffice.gc.ca/banner/ ||webdesignerdepot.com/wp-content/plugins/md-popup/ ||webdesignerdepot.com/wp-content/themes/wdd2/fancybox/ ||webhostingtalk.com/images/style/lw-160x400.jpg ||webhostingtalk.com/images/style/lw-header.png ||webhostranking.com/images/bluehost-coupon-banner-1.gif ||webmailnotifier.mozdev.org/etc/af/ ||webmaster.extabit.com^ ||webmastercrunch.com^*/hostgator300x30.gif ||webnewswire.com/images/banner ||websitehome.co.uk/seoheap/cheap-web-hosting.gif ||webstatschecker.com/links/ ||weddingtv.com/src/baners/ ||weei.com^*/sponsors/ ||weei.com^*_banner.jpg ||wegoted.com/includes/biogreen.swf ||wegoted.com/uploads/memsponsor/ ||wegoted.com/uploads/sponsors/ ||weknowmemes.com/sidesky. ||werlv.com^*banner ||wgfaradio.com/images/banners/ ||whatismyip.com/images/VYPR__125x125.png ||whatismyip.com/images/vyprvpn_ ||whatismyip.org/ez_display_au_fillslot.js ||whatmobile.com.pk/banners/ ||whatmyip.co/images/speedcoin_ ||whatreallyhappened.com/webpageimages/banners/uwslogosm.jpg ||whatsabyte.com/images/Acronis_Banners/ ||whatson.co.za/img/hp.png ||whatsonstage.com/images/sitetakeover/ ||whatsontv.co.uk^*/promo/ ||whatsthescore.com/logos/icons/bookmakers/ ||whdh.com/images/promotions/ ||wheninmanila.com/wp-content/uploads/2011/05/Benchmark-Email-Free-Signup.gif ||wheninmanila.com/wp-content/uploads/2012/12/Marie-France-Buy-1-Take-1-Deal-Discount-WhenInManila.jpg ||wheninmanila.com/wp-content/uploads/2014/02/DTC-Hardcore-Quadcore-300x100.gif ||wheninmanila.com/wp-content/uploads/2014/04/zion-wifi-social-hotspot-system.png ||whispersinthecorridors.com/banner ||whistleout.com.au/imagelibrary/ads/wo_skin_ ||whitepages.ae/images/UI/FC/ ||whitepages.ae/images/UI/LB/ ||whitepages.ae/images/UI/MR/ ||whitepages.ae/images/UI/SR/ ||whitepages.ae/images/UI/SRA/ ||whitepages.ae/images/UI/SRB/ ||whitepages.ae/images/UI/WS/ ||who.is/images/domain-transfer2.jpg ||whoer.net/images/pb/ ||whoer.net/images/vpnlab20_ ||whois.net/dombot.php? ||whois.net/images/banners/ ||whoownsfacebook.com/images/topbanner.gif ||whtsrv3.com^*==$domain=webhostingtalk.com ||widget.directory.dailycommercial.com^ ||widih.org/banners/ ||wiilovemario.com/images/fc-twin-play-nes-snes-cartridges.png ||wikia.com/__varnish_ ||wikinvest.com/wikinvest/ads/ ||wikinvest.com/wikinvest/images/zap_trade_ ||wildtangent.com/leaderboard? ||windows.net/script/p.js$domain=1fichier.com|limetorrents.cc|primewire.ag|thepiratebay.みんな ||windowsitpro.com^*/roadblock. ||winnfm.com/grfx/banners/ ||winpcap.org/assets/image/banner_ ||winsupersite.com^*/roadblock. ||wipfilms.net^*/amazon.png ||wipfilms.net^*/instant-video.png ||wired.com/images/xrail/*/samsung_layar_ ||wirenh.com/images/banners/ ||wiretarget.com/a_$subdocument ||witbankspurs.co.za/layout_images/sponsor.jpg ||witteringsfromwitney.com/wp-content/plugins/popup-with-fancybox/ ||wjie.org/media/img/sponsers/ ||wjunction.com/images/468x60 ||wjunction.com/images/constant/ ||wjunction.com/images/rectangle ||wksu.org/graphics/banners/ ||wlcr.org/banners/ ||wlrfm.com/images/banners/ ||wned.org/underwriting/sponsors/ ||wnst.net/img/coupon/ ||wolf-howl.com/wp-content/banners/ ||worddictionary.co.uk/static//inpage-affinity/ ||wordpress.com^*-banner-$domain=inspirationfeed.com ||wordpress.com^*/amazon2-center-top.$domain=gigaom.com ||wordpress.com^*/chive-skin-$image,domain=thechive.com ||wordpress.com^*/mediatemple.jpg$domain=inspirationfeed.com ||wordpress.com^*_250x2501.$domain=inspirationfeed.com ||wordpress.com^*_reskin-$image,domain=bossip.com ||wordreference.com/*/publ/ ||wordwebonline.com/img/122x36ccbanner.png ||work-day.co.uk/pub_ ||workingdays.ca/pub_ ||workingdays.org/pub_ ||workingdays.us/pub_ ||worldarchitecturenews.com/banner/ ||worldarchitecturenews.com/flash_banners/ ||worldometers.info/L300L.html ||worldometers.info/L300R.html ||worldometers.info/L728.html ||worldstadiums.com/world_stadiums/bugarrishoes/ ||worldstagegroup.com/banner/ ||worldstagegroup.com/worldstagenew/banner/ ||worthofweb.com/images/wow-ad- ||wowhead.com/uploads/skins/$image ||wowwiki.com/__varnish_ ||wp.com/wp-content/themes/vip/tctechcrunch/images/tc_*_skin.jpg ||wp.com^*/coedmagazine3/gads/$domain=coedmagazine.com ||wpcomwidgets.com^$domain=thegrio.com ||wpcv.com/includes/header_banner.htm ||wpdaddy.com^*/banners/ ||wptmag.com/promo/ ||wqah.com/images/banners/ ||wqam.com/partners/ ||wqxe.com/images/sponsors/ ||wranglerforum.com/images/sponsor/ ||wrc.com/img/sponsors- ||wrc.com/swf/homeclock_edox_hori.swf ||wrcjfm.org/images/banners/ ||wrko.com/sites/wrko.com/files/poll/*_285x95.jpg ||wrko.com^*/sponsors/ ||wrlr.fm/images/banners/ ||wrmf.com/upload/*_Webskin_ ||wshh.me/vast/ ||wsj.net/internal/krux.js ||wttrend.com/images/hs.jpg ||wunderground.com/geo/swfad/ ||wunderground.com^*/wuss_300ad2.php? ||wvbr.com/images/banner/ ||wwaytv3.com^*/curlypage.js ||wwbf.com/b/topbanner.htm ||www2.sys-con.com^*.cfm ||x.castanet.net^ ||xbitlabs.com/cms/module_banners/ ||xbitlabs.com/images/banners/ ||xbox-hq.com/html/images/banners/ ||xbox-scene.com/crave/logo_on_white_s160.jpg ||xboxgaming.co.za^*/images/background/ ||xiaopan.co/Reaver.png ||xomreviews.com/sponsors/ ||xoops-theme.com/images/banners/ ||xscores.com/livescore/banners/ ||xsreviews.co.uk/style/bgg2.jpg ||xtremesystems.org/forums/brotator/ ||xup.in/layer.php ||yahoo.*/serv?s= ||yahoo.com/__darla/ ||yahoo.com/contextual-shortcuts ||yahoo.com/darla/ ||yahoo.com/livewords/ ||yahoo.com/neo/darla/ ||yahoo.com/sdarla/ ||yahoo.com/ysmload.html? ||yahoo.com^*/eyc-themis? ||yamgo.mobi/images/banner/ ||yamivideo.com^*/download_video.jpg ||yardbarker.com/asset/asset_source/*?ord=$subdocument ||yarisworld.com^*/banners/ ||yasni.*/design/relaunch/gfx/elitepartner_ ||yavideo.tv/ajaxlog.txt? ||yea.uploadimagex.com^ ||yellow.co.ke/img/left_side/ ||yellow.co.ke/img/right_side/ ||yellow.co.ke/img/top_banner/ ||yellowpage-jp.com/images/banners/ ||yellowpages.ae/UI/FC/ ||yellowpages.ae/UI/LB/ ||yellowpages.ae/UI/MR/ ||yellowpages.ae/UI/SR/ ||yellowpages.ae/UI/ST/ ||yellowpages.ae/UI/WA/ ||yellowpages.ae/UI/WM/ ||yellowpages.com.jo/banners/ ||yellowpages.com.lb/uploaded/banners/ ||yellowpages.ly/user_media/banner/ ||yellowpages.ly^*/sponsors/ ||yellowpageskenya.com/sponsored/ ||yfrog.com/images/contests/ ||yfrog.com/images/weezer-bloggie-bg.png ||yfrog.com/ym.php? ||yimg.com/*300x250$image,object ||yimg.com/a/1-$~stylesheet ||yimg.com/ao/adv/$script,domain=yahoo.com ||yimg.com/cv/ae/ca/audience/$image,domain=yahoo.com ||yimg.com/cv/ae/us/audience/$image,domain=yahoo.com ||yimg.com/cv/eng/*.webm$domain=yahoo.com ||yimg.com/cv/eng/*/635x100_$domain=yahoo.com ||yimg.com/cv/eng/*/970x250_$domain=yahoo.com ||yimg.com/dh/ap/default/*/skins_$image,domain=yahoo.com ||yimg.com/hl/ap/*_takeover_$domain=yahoo.com ||yimg.com/hl/ap/default/*_background$image,domain=yahoo.com ||yimg.com/i/i/de/cat/yahoo.html$domain=yahoo.com ||yimg.com/la/i/wan/widgets/wjobs/$subdocument,domain=yahoo.com ||yimg.com/rq/darla/$domain=yahoo.com ||yimg.com^*/billboardv2r5min.js$domain=yahoo.com ||yimg.com^*/darla-secure-pre-min.js$domain=yahoo.com ||yimg.com^*/fairfax/$image ||yimg.com^*/flash/promotions/ ||yimg.com^*/ya-answers-dmros-ssl-min.js$domain=yahoo.com ||yimg.com^*/yad*.js$domain=yahoo.com ||yimg.com^*/yad.html ||yimg.com^*/yfpadobject.js$domain=yahoo.com ||yimg.com^*_east.swf$domain=yahoo.com ||yimg.com^*_north.swf$domain=yahoo.com ||yimg.com^*_west.swf$domain=yahoo.com ||ynaija.com^*/ad. ||ynaija.com^*300x250 ||ynaija.com^*300X300 ||yolasite.com/resources/$domain=coolsport.tv ||yomzansi.com^*-300x250. ||yopmail.com/fbd.js ||yorkshirecoastradio.com/resources/creative/ ||youconvertit.com/_images/*ad.png ||youngrider.com/images/sponsorships/ ||yourbittorrent.com/downloadnow.png ||yourbittorrent.com/images/lumovies.js ||yourepeat.com/revive_wrapper? ||yourepeat.com^*/skins/ ||yourfilehost.com/ads/ ||yourindustrynews.com/ads/ ||yourmovies.com.au^*/side_panels_ ||yourmuze.fm/images/audionow.png ||yourmuze.fm/images/banner_ym.png ||yourradioplace.com//images/banners/ ||yourradioplace.com/images/banners/ ||yourwire.net/images/refssder.gif ||youserials.com/i/banner_pos.jpg ||youtube-mp3.org/acode/ ||youtube.com/yva_video?adformat=$object-subrequest,domain=nfl.com|viki.com ||youtubeproxy.pk/images/Indiansongs.pk.jpg ||youtubeproxy.pk/images/Lahore.fm.jpg ||youtubeproxy.pk/images/lahore.jpg ||youwatch.org/iframe1.html ||yp.mo^*/ads/ ||ytimg.com^*/new_watch_background.jpg?$domain=youtube.com ||ytimg.com^*/new_watch_background_*.jpg?$domain=youtube.com ||ytimg.com^*_banner$domain=youtube.com ||ytmnd.com/ugh ||yudu.com^*_intro_ads ||zabasearch.com/search_box.php?*&adword= ||zam.com/i/promos/*-skin. ||zambiz.co.zm/banners/ ||zamimg.com/images/skins/ ||zamimg.com/shared/minifeatures/ ||zanews.co.za^*/banners/ ||zap2it.com/dfp/production/$script ||zap2it.com/wp-content/themes/overmind/js/zcode- ||zattoo.com/ads/ ||zawya.com/ads/ ||zawya.com/brands/ ||zbc.co.zw^*/banners/ ||zeetvusa.com/images/CARIBBEN.jpg ||zeetvusa.com/images/hightlow.jpg ||zeetvusa.com/images/SevaWeb.gif ||zerochan.net/skyscraper.html ||zeropaid.com/images/ ||zeropaid.com^*/94.jpg ||ziddu.com/images/140x150_egglad.gif ||ziddu.com/images/globe7.gif ||ziddu.com/images/wxdfast/ ||zigzag.co.za/images/oww- ||zipcode.org/site_images/flash/zip_v.swf ||zombiegamer.co.za/wp-content/uploads/*-skin- ||zomobo.net/images/removeads.png ||zonein.tv/add$subdocument ||zoneradio.co.za/img/banners/ ||zoomin.tv/decagonhandler/ ||zootoday.com/pub/21publish/Zoo-navtop-casino_ ||zootoday.com/pub/21publish/Zoo-navtop-poker.gif ||zoover.*/shared/bannerpages/darttagsbanner.aspx? ||zoozle.org/if.php?q= ||zophar.net/files/tf_ ||zorrovpn.com/static/img/promo/ ||zpag.es/b/ ||zshares.net/fm.html ||zurrieqfc.com/images/banners/ ! extratorrentlive /\/[a-zA-Z0-9]{3}/$script,third-party,domain=extratorrent.cc|extratorrentlive.com ! Filenuke/sharesix /\.filenuke\.com/.*[a-zA-Z0-9]{4}/$script /\.sharesix\.com/.*[a-zA-Z0-9]{4}/$script ! Yavli.com /http://[a-z]\.[a-zA-Z0-9-]+\.[a-z]+\/.*(?:[!"#$%&'()*+,:;<=>?@/\^_`{|}~-])/$script,third-party,xmlhttprequest,domain=247wallst.com|activistpost.com|alfonzorachel.com|allenbwest.com|allenwestrepublic.com|americanlivewire.com|askmefast.com|barbwire.com|blacklistednews.com|breathecast.com|brosome.com|bulletsfirst.net|chacha.com|cheezburger.com|christianpost.com|christiantoday.com|cinemablend.com|clashdaily.com|classicalite.com|comicallyincorrect.com|comicbookmovie.com|conservativebyte.com|conservativevideos.com|cowboybyte.com|crossmap.com|dailycaller.com|dailysurge.com|dccrimestories.com|dealbreaker.com|designntrend.com|digitaljournal.com|drhotze.com|gamerant.com|genfringe.com|girlsjustwannahaveguns.com|hallels.com|hellou.co.uk|hngn.com|infowars.com|instigatornews.com|investmentwatchblog.com|joblo.com|joeforamerica.com|kdramastars.com|kpopstarz.com|latinpost.com|libertyunyielding.com|listverse.com|makeuseof.com|mensfitness.com|minutemennews.com|moddb.com|mstarz.com|muscleandfitness.com|musictimes.com|naturalnews.com|natureworldnews.com|newser.com|oddee.com|okmagazine.com|opposingviews.com|patriotoutdoornews.com|patriotupdate.com|pitgrit.com|politicususa.com|product-reviews.net|radaronline.com|realfarmacy.com|redmaryland.com|screenrant.com|shark-tank.com|stevedeace.com|techtimes.com|theblacksphere.net|theblaze.com|thefreedictionary.com|thegatewaypundit.com|theladbible.com|thelibertarianrepublic.com|themattwalshblog.com|townhall.com|unilad.co.uk|uniladmag.com|unitrending.co.uk|valuewalk.com|vcpost.com|victoriajackson.com|viralnova.com|whatculture.com|wimp.com|wwitv.com /http://[a-z]\.[a-zA-Z0-9-]+\.[a-z]+\/.*[a-zA-Z0-9]+/$script,third-party,domain=247wallst.com|activistpost.com|alfonzorachel.com|allenbwest.com|allenwestrepublic.com|americanlivewire.com|askmefast.com|barbwire.com|blacklistednews.com|breathecast.com|brosome.com|bulletsfirst.net|chacha.com|cheezburger.com|christianpost.com|christiantoday.com|cinemablend.com|clashdaily.com|classicalite.com|comicallyincorrect.com|comicbookmovie.com|conservativebyte.com|conservativevideos.com|cowboybyte.com|crossmap.com|dailycaller.com|dailysurge.com|dccrimestories.com|dealbreaker.com|designntrend.com|digitaljournal.com|drhotze.com|gamerant.com|genfringe.com|girlsjustwannahaveguns.com|hallels.com|hellou.co.uk|hngn.com|infowars.com|instigatornews.com|investmentwatchblog.com|joblo.com|joeforamerica.com|kdramastars.com|kpopstarz.com|latinpost.com|libertyunyielding.com|listverse.com|makeuseof.com|mensfitness.com|minutemennews.com|moddb.com|mstarz.com|muscleandfitness.com|musictimes.com|naturalnews.com|natureworldnews.com|newser.com|oddee.com|okmagazine.com|opposingviews.com|patriotoutdoornews.com|patriotupdate.com|pitgrit.com|politicususa.com|product-reviews.net|radaronline.com|realfarmacy.com|redmaryland.com|screenrant.com|shark-tank.com|stevedeace.com|techtimes.com|theblacksphere.net|theblaze.com|thefreedictionary.com|thegatewaypundit.com|theladbible.com|thelibertarianrepublic.com|themattwalshblog.com|townhall.com|unilad.co.uk|uniladmag.com|unitrending.co.uk|valuewalk.com|vcpost.com|victoriajackson.com|viralnova.com|whatculture.com|wimp.com|wwitv.com @@/wp-content/plugins/akismet/*$script @@||c.gnli.com^$script,third-party @@||cdn.api.twitter.com*http%$script,third-party @@||hwcdn.net/*.js?$script @@||intensedebate.com/js/$script,third-party @@||launch.newsinc.com/*/js/embed.js$script,third-party @@||lps.newsinc.com/player/show/$script @@||p.jwpcdn.com/*/jwpsrv.js$script,third-party @@||p.jwpcdn.com^$script,third-party @@||s.gravatar.com^$script,third-party @@||trc.taboola.com*http%$script,third-party ! Firefox freezes if not blocked on reuters.com (http://forums.lanik.us/viewtopic.php?f=64&t=16854) ||static.crowdscience.com/max-*.js?callback=crowdScienceCallback$domain=reuters.com ! Anti-Adblock .com/lib/f=$third-party,xmlhttprequest,domain=sporcle.com /ailde.$domain=cbs.com |http://*=*&$third-party,xmlhttprequest,domain=sporcle.com ||ailde.com^$domain=cbs.com ||alidw.net^$domain=cbs.com ||amazonaws.com^$script,domain=dsero.com|ginormousbargains.com|korean-candy.com|misheel.net|politicususa.com|techydoor.com|trutower.com|unfair.co ||channel4.com^*.innovid.com$object-subrequest ||channel4.com^*.tidaltv.com$object-subrequest ||histats.com/js15.js$domain=televisaofutebol.com ||http.anno.channel4.com*- ||http.anno.channel4.com*_*_*_ ||joindota.com/img/*LB_$image ||joindota.com/img/*MR_$image ||no-ip.biz^$script,domain=dsero.com|korean-candy.com|misheel.net|politicususa.com|techydoor.com|trutower.com ||pagefair.com/static/adblock_detection/js/d.min.js$domain=majorleaguegaming.com ||servebeer.com^$domain=dsero.com|korean-candy.com|misheel.net|politicususa.com|techydoor.com|trutower.com ||servemp3.com^$script,domain=dsero.com|korean-candy.com|misheel.net|politicususa.com|techydoor.com|trutower.com ||servepics.com^$script,domain=dsero.com|korean-candy.com|misheel.net|politicususa.com|techydoor.com|trutower.com ||servequake.com^$script,domain=dsero.com|korean-candy.com|misheel.net|politicususa.com|techydoor.com|trutower.com ||sytes.net^$script,domain=dsero.com|korean-candy.com|misheel.net|politicususa.com|techydoor.com|trutower.com ||vapingunderground.com/js/vapingunderground/fucking_adblock.js ||watchfreeinhd.com/js/adblocker.js ||ytconv.net/site/adblock_detect ||zapto.org^$script,domain=dsero.com|korean-candy.com|misheel.net|politicususa.com|techydoor.com|trutower.com ! Non-English (instead of whitelisting ads) ||youtube.com/yva_video?adformat=$object-subrequest,domain=antena3.com|atresplayer.com|lasexta.com ! Mobile ! *** easylist:easylist/easylist_specific_block_popup.txt *** /sendspace-pop.$popup,domain=sendspace.com ^utm_source=$popup,domain=sex.com|thepiratebay.se |http:$popup,third-party,domain=allmyvideos.net|embed.videoweed.es|extreme-board.com|filepost.com|filmovizija.com|go4up.com|imagebam.com|imageporter.com|imgbox.com|imgmade.com|imgspice.com|load.to|mofunzone.com|putlocker.is|vidspot.net|watchcartoononline.com|xtshare.com ||4fuckr.com/api.php$popup ||adf.ly^$popup,domain=uploadcore.com|urgrove.com ||adx.kat.ph^$popup ||adyou.me/bug/adcash$popup ||aiosearch.com^$popup,domain=torrent-finder.info ||allmyvideos.net^*?p=$popup ||avalanchers.com/out/$popup ||bangstage.com^$popup,domain=datacloud.to ||bit.ly^$popup,domain=fastvideo.eu|rapidvideo.org ||casino-x.com^*&promo$popup ||channel4.com/ad/$popup ||click.aliexpress.com^$popup,domain=multiupfile.com ||cloudzilla.to/cam/wpop.php$popup ||comicbookmovie.com/plugins/ads/$popup ||conservativepost.com/pu/$popup ||damoh.muzu.tv^$popup ||deb.gs^*?ref=$popup ||edomz.com/re.php?mid=$popup ||f-picture.net/Misc/JumpClick?$popup ||fashionsaga.com^$popup,domain=putlocker.is ||filepost.com/default_popup.html$popup ||filmon.com^*&adn=$popup ||findgrid.com^$popup,domain=amaderforum.com ||finegame.org^$popup,domain=bestreams.net ||firedrive.com/appresources/$popup ||firedrive.com/tools/$popup ||flashx.tv/ads/$popup ||flashx.tv/frame/$popup ||free-filehost.net/pop/$popup ||free-stream.tv^$popup,domain=flashx.tv ||freean.us^*?ref=$popup ||fullonsms.com/blank.php$popup ||fullonsms.com/mixpop.html$popup ||fullonsms.com/quikr.html$popup ||fullonsms.com/quikrad.html$popup ||fullonsms.com/sid.html$popup ||gamezadvisor.com/popup.php$popup ||goo.gl^$popup,domain=amaderforum.com|jumbofile.net|videomega.tv ||google.com.eg/url?$popup,domain=hulkload.com ||gratuit.niloo.fr^$popup,domain=simophone.com ||hide.me^$popup,domain=ncrypt.in ||homerun.re/adServe/$popup ||homets.info/queen_file?$popup ||houndmirror.com/out.php$popup ||href.li^$popup,domain=300mblink.com ||ifly.com/trip-plan/ifly-trip?*&ad=$popup ||imageshack.us/ads/$popup ||imageshack.us/newuploader_ad.php$popup ||intradayfun.com/news_intradayfun.com.html$popup ||itv.com/itv/adclick/$popup ||jokertraffic.com^$popup,domain=4fuckr.com ||kalemaro.com^$popup,domain=filatak.com ||leaderdownload.com^$popup,domain=fiberupload.net ||limbohost.net^$popup,domain=tusfiles.net ||linkbucks.com^*?ref=$popup ||military.com/data/popup/new_education_popunder.htm$popup ||miniurls.co^*?ref=$popup ||multiupload.nl/popunder/$popup ||nesk.co^$popup,domain=veehd.com ||newsgate.pw^$popup,domain=adjet.biz ||nosteam.ro/pma/$popup ||oddschecker.com/clickout.htm?type=takeover-$popup ||pamaradio.com^$popup,domain=secureupload.eu ||park.above.com^$popup ||photo4sell.com^$popup,domain=filmovizija.com ||plarium.com/play/*adCampaign=$popup ||playhd.eu/test$popup ||pop.billionuploads.com^$popup ||r.search.yahoo.com/_ylt=*;_ylu=*.r.msn.com$popup,domain=search.yahoo.com ||rediff.com/uim/ads/$popup ||schenkelklopfer.org^$popup,domain=4fuckr.com ||single-vergleich.de^$popup,domain=netload.in ||softexter.com^$popup,domain=2drive.net ||songspk.cc/pop*.html$popup ||spendcrazy.net^$popup,third-party,domain=animegalaxy.net|animenova.tv|animetoon.tv|animewow.eu|gogoanime.com|goodanime.eu|gooddrama.net|toonget.com ||sponsorselect.com/Common/LandingPage.aspx?eu=$popup ||streamcloud.eu/deliver.php$popup ||streamtunerhd.com/signup?$popup,third-party ||subs4free.com/_pop_link.php$popup ||thebestbookies.com^$popup,domain=fırstrowsports.eu ||thesource.com/magicshave/$popup ||titanbrowser.com^$popup,domain=amaderforum.com ||titanshare.to/download-extern.php?type=*&n=$popup ||tny.cz/red/first.php$popup ||toptrailers.net^$popup,domain=kingfiles.net|uploadrocket.net ||torrentz.*/mgidpop/$popup ||torrentz.*/wgmpop/$popup ||torrentz.eu/p/$popup ||tripadvisor.*/rulebasedpopunder?$popup ||tripadvisor.*/SimilarHotelsPopunder?$popup ||vibeo.to^$popup,domain=flashx.tv ||vidhog.com/ilivid-redirect.php$popup ||vidspot.net^*http$popup ||virtualtourist.com/commerce/popunder/$popup ||vodu.ch/play_video.php$popup ||watch-movies.net.in/popup.php$popup ||watchclip.tv^$popup,domain=hipfile.com ||wegrin.com^$popup,domain=watchfreemovies.ch ||yasni.ca/ad_pop.php$popup ||zanox.com^$popup,domain=pregen.net ||ziddu.com/onclickpop.php$popup ||zmovie.tv^$popup,domain=deditv.com|vidbox.net ! *** easylist:easylist_adult/adult_specific_block.txt *** .info^$script,domain=pornhub.com /[a-z0-9A-Z]{6}/$xmlhttprequest,domain=pornhub.com|redtube.com|tube8.com|tube8.es|tube8.fr|youporn.com /\/[0-9].*\-.*\-[a-z0-9]{4}/$script,xmlhttprequest,domain=gaytube.com|keezmovies.com|spankwire.com|tube8.com|tube8.es|tube8.fr /http://.*[a-z0-9]{3}.*(?:[!"#$%&'()*+,:;<=>?@/\^_`{|}~-]).*[a-z0-9]{3}.*(?:[!"#$%&'()*+,:;<=>?@/\^_`{|}~-])/$xmlhttprequest,domain=pornhub.com|redtube.com|tube8.com|tube8.es|tube8.fr|youporn.com /http://[a-zA-Z0-9]+\.[a-z]+\/.*(?:[!"#$%&'()*+,:;<=>?@/\^_`{|}~-]).*[a-zA-Z0-9]+/$script,third-party,domain=keezmovies.com|pornhub.com|redtube.com|tube8.com|tube8.es|tube8.fr|youporn.com ||109.201.146.142^$domain=xxxbunker.com ||213.174.140.38/bftv/js/msn- ||213.174.140.38^*/msn-*.js$domain=boyfriendtv.com|pornoxo.com ||244pix.com/webop.jpg ||24porn7.com/24roll.html ||24porn7.com/300.php ||24porn7.com/banned/ ||24porn7.com/ebanners/ ||24porn7.com/float/float_adplib.js ||24porn7.com/imads/ ||24porn7.com/odd.php ||24porn7.com/right3.php ||24porn7.com/toonad/ ||2adultflashgames.com/images/v12.gif ||2adultflashgames.com/img/ ||2adultflashgames.com/teaser/teaser.swf ||3xupdate.com^*/ryushare.gif ||3xupdate.com^*/ryushare2.gif ||3xupdate.com^*/ryusharepremium.gif ||3yen.com/wfn_ ||5ilthy.com/porn.php ||64.62.202.124^*/cumlouder.jpg ||a.eporner.com^ ||a.heavy-r.com^ ||a.killergram-girls.com^ ||abc-celebs.com/spons/ ||absoluporn.com/code/pub/ ||ad.eporner.com^ ||ad.slutload.com^ ||ad.thisav.com^ ||ad.userporn.com^ ||adrive.com/images/fc_banner.jpg ||ads.xxxbunker.com^ ||adult-profit-files.com/banner ||adult-sex-games.com/images/promo/ ||adultfilmdatabase.com/graphics/banners/ ||adultfyi.com/images/banners/ ||adultwork.com/images/AWBanners/ ||affiliates.goodvibes.com^ ||alladultnetwork.tv/main/videoadroll.xml ||alotporn.com/media/banners/ ||alotporn.com^*/js/oopopw.js ||amadorastube.com^*/banner_ ||amateur-desire.com/pics/724x90d.jpg ||amateur-desire.com/pics/sm_ ||amateur-streams.com^*/popup.js ||amateuralbum.net/affb.html ||amateurfarm.net/layer.js ||analtubegirls.com/js/realamateurtube.js ||andtube.com/ban_ ||angelshack.com/images/under-video.png ||arionmovies.com/*/popup.php ||asexstories.com/010ads/ ||asgayas.com/floater/ ||asgayas.com/popin.js ||asianpornmovies.com/images/banners/ ||asspoint.com/images/banners/ ||avn.com/templates/avnav/skins/ ||axatube.com/dos.html ||babblesex.com/js/misc.js ||babedrop.com/babelogger_images/ ||babepicture.co.uk^*banner ||babesandstars.com/images/a/ ||babesandstars.com/thumbs/paysites/ ||babeshows.co.uk/fvn53.jpg ||babeshows.co.uk^*banner ||babesmachine.com/html/ ||badjojo.com/js/scripts- ||bagslap.com/*.html ||bangyoulater.com/images/banners_ ||bangyoulater.com/pages/aff.php ||banner1.pornhost.com^ ||banners.cams.com^ ||befuck.com/befuck_html/ ||befuck.com/js/adpbefuck ||bellyboner.com/facebookchatlist.php ||bigboobs.hu/banners/ ||bigxvideos.com/js/focus.*.js ||bigxvideos.com/js/pops2. ||bigxvideos.com/js/popu. ||bigxvideos.com/rec/ ||blackonasianblog.com/uploads/banners/ ||blackredtube.com/fadebox2.js ||bob.crazyshit.com^ ||bonbonme.com/js/cams.js ||bonbonme.com/js/dticash/ ||bonbonme.com/js/rightbanner.js ||bonbonsex.com/js/dl/bottom.js ||bonbonsex.com/js/workhome.js ||boneprone.com/premium.html ||boobieblog.com/submityourbitchbanner3.jpg ||boobieblog.com/TilaTequilaBackdoorBanner2.jpg ||bralesscelebs.com/*banner ||bralesscelebs.com/160x600hcp.gif ||bralesscelebs.com/160x600ps.gif ||bralesscelebs.com/320x240ps.gif ||bravotube.net/dd$subdocument ||bravotube.net/dp.html ||bravotube.net/if/$subdocument ||brcache.madthumbs.com^ ||bunnylust.com/sponsors/ ||bustnow.com/xv/ad/ ||bustnow.com/xv/x/002.php ||bustnow.com^*/999.js.php ||bustnow.com^*/sponsors/ ||cameltoe.com^*/banners/ ||canadianhottie.ca/images/banners/ ||celeb.gate.cc/banner/ ||celeb.gate.cc/misc/event_*.js ||celebritypink.com/bannedcelebs- ||chanweb.info/en/adult/hc/local_include/ ||chubby-ocean.com/banner/ ||clips-and-pics.org/clipsandpics.js ||comdotgame.com/vgirl/ ||coolmovs.com/js/focus.*.js ||coolmovs.com/rec/$subdocument ||crackwhoreconfessions.com/images/banners/ ||crazyshit.com/p0pzIn.js ||creampietubeporn.com/ctp.html ||creampietubeporn.com/porn.html ||creatives.cliphunter.com^ ||creatives.pichunter.com^ ||creepshots.com^*/250x250_ ||data18.com^*/banners/ ||definebabe.com/db/images/leftnav/webcams2.png ||definebabe.com/db/js/pcme.js ||definebabe.com/sponsor/ ||definefetish.com/df/js/dpcm.js ||deliciousbabes.org/banner/ ||deliciousbabes.org/media/banners/ ||depic.me/banners/ ||destroymilf.com/popup%20floater.js ||devatube.com/img/partners/ ||diamond-tgp.com/fp.js ||dickbig.net/scr/ ||dirtypriest.com/sexpics/ ||dominationtube.com/exit.js ||dot.eporner.com^ ||dot2.eporner.com^ ||dronporn.com/main-video-place.html ||dronporn.com/tizer.html ||drtuber.com/promo/banners/ ||drtuber.com/templates/frontend/white/js/embed.js? ||drtuber.com^*/aff_banner.swf ||dusttube.com/pop*.js ||easypic.com/js/easypicads.js ||eccie.net/buploads/ ||eccie.net/eros/ ||efukt.com^*.php$subdocument ||egoporn.com/themagic.js ||egoporn.com/videotop.gif ||empflix.com/embedding_player/600x474_ ||empireamateurs.com/images/*banner ||entensity.net/crap/ ||epicwank.com/social/jquery.stp.min.js ||eporner.com/pjsall-*.js ||eporner.com^$subdocument,~third-party ||eroprofile.com/js/pu*.js ||eskimotube.com/kellyban.gif ||exhentai.net/img/aaf1.gif ||exit.macandbumble.com^ ||extreme-board.com/bannrs/ ||extremetube.com/player_related? ||fapdick.com/uploads/fap_ ||fastpic.ru/js_f2.jpg ||fastpic.ru/js_h2.jpg ||femdom-fetish-tube.com/popfemdom.js ||fetishok.com/js/focus.$script ||fetishok.com/rec/$subdocument ||fileshare.ro^*/dhtmlwindow.js ||filthyrx.com/images/porno/ ||filthyrx.com/inline.php? ||filthyrx.com/rx.js ||finehub.com/p3.js ||fingerslam.com/*.html ||fleshbot.com/wp-content/themes/fbdesktop_aff/images/af ||floppy-tits.com/iframes/ ||free-celebrity-tube.com/js/freeceleb.js ||freebunker.com/includes/js/cat.js ||freebunker.com^*/ex.js ||freebunker.com^*/exa.js ||freebunker.com^*/layer.js ||freebunker.com^*/oc.js ||freebunker.com^*/pops.js ||freebunker.com^*/raw.js ||freeimgup.com/xxx/content/system/js/iframe.html ||freeones.com/images/freeones/sidewidget/$image ||freeporn.to/wpbanner/ ||freeporninhd.com/images/cbside.gif ||freepornvs.com/im.js ||fuckuh.com/pr_ad.swf ||funny-games.biz/banners/ ||galleries-pornstar.com/thumb_top/ ||gals4free.net/images/banners/ ||gamesofdesire.com/images/banners/ ||gapeandfist.com/uploads/thumbs/ ||gayporntimes.com/img/GP_Heroes.jpg ||gayporntimes.com^*/Bel-Ami-Mick-Lovell-July-2012.jpeg ||gayporntimes.com^*/CockyBoys-July-2012.jpg ||gaytube.com/chacha/ ||gggtube.com/images/banners/ ||ghettotube.com/images/banners/ ||gina-lynn.net/pr4.html ||girlfriendvideos.com/pcode.js ||girlsfrombudapest.eu/banners/ ||girlsfromprague.eu/banners/ ||girlsfromprague.eu^*468x ||girlsintube.com/images/get-free-server.jpg ||girlsnaked.net/gallery/banners/ ||girlsofdesire.org/banner/ ||girlsofdesire.org/media/banners/ ||glamour.cz/banners/ ||gloryholegirlz.com/images/banners/ ||goldporntube.com/iframes/ ||gotgayporn.com/Watermarks/ ||grannysexforum.com/filter.php ||h2porn.com/contents/content_sources/ ||hanksgalleries.com/aff- ||hanksgalleries.com/gallery- ||hanksgalleries.com/galleryimgs/ ||hanksgalleries.com/stxt_ ||hanksgalleries.com/vg_ad_ ||hardsextube.com/pornstars/$xmlhttprequest ||hardsextube.com/preroll/getiton/ ||hardsextube.com/testxml.php ||hardsextube.com/zone.php ||hawaiipornblog.com/post_images/ ||hcomicbook.com/banner/ ||hcomicbook.com/js/hcb-$script ||hcomicbook.com^*_banner1.gif ||hdporn.in/images/rec/ ||hdporn.in/js/focus.*.js ||hdporn.in/js/pops2. ||hdporn.in/rec/$subdocument ||hdporn.net/images/hd-porn-banner.gif ||heavy-r.com/a/ ||heavy-r.com/js/imbox.js ||hebus.com/p/hebusx/ ||hellporno.com/iframes/ ||hentai-foundry.com/themes/*/add$image ||hentai-foundry.com/themes/*Banner ||hentai-foundry.com/themes/Hentai/images/hu/hu.jpg ||hentairules.net/pop_$script ||hentaistream.com/out/ ||hentaistream.com/wp-includes/images/bg- ||hentaistream.com/wp-includes/images/mofos/webcams_ ||heraldnet.com/section/iFrame_AutosInternetSpecials? ||heraldnetdailydeal.com/widgets/DailyDealWidget300x250 ||hgimg.com/js/beacon. ||hidefporn.ws/04.jpg ||hidefporn.ws/05.jpg ||hidefporn.ws/055.jpg ||hidefporn.ws/client ||hidefporn.ws/img.png ||hidefporn.ws/nitro.png ||hollyscoop.com/sites/*/skins/ ||hollywoodoops.com/img/*banner ||homegrownfreaks.net/homegfreaks.js ||homemademoviez.com^$subdocument ||homeprivatevids.com/banner2.shtml ||homeprivatevids.com/banners.shtml ||hornygamer.com/images/promo/ ||hornywhores.net/hw$script ||hornywhores.net/img/double.jpg ||hornywhores.net/img/zevera_rec.jpg ||hostingfailov.com/image/tablespons_ ||hostingfailov.com/image/tank3.gif ||hostingfailov.com^*_1000x100.swf ||hotdevonmichaels.com^*/pf_640x1001.jpg ||hotdevonmichaels.com^*/streamate2.jpg ||hotdevonmichaels.com^*/wicked.gif ||hotdylanryder.com^*/Big-Tits-Like-Big-Dicks.jpg ||hotdylanryder.com^*/dylan_350x250_01.jpg ||hotdylanryder.com^*/iframes_174.jpg ||hotdylanryder.com^*/pf_640x100.jpg ||hotdylanryder.com^*/wicked.gif ||hotkellymadison.com^*/kelly1.jpg ||hotkellymadison.com^*/kelly4.jpg ||hotkellymadison.com^*/km_300x300.gif ||hotkellymadison.com^*/pf_640x100.jpg ||hotsashagrey.com^*/Anabolic.jpg ||hotsashagrey.com^*/New_Sensations-1091.gif ||hotsashagrey.com^*/PeterNorth-800x350.jpg ||hotsashagrey.com^*/squ-fantasygirlsasha-001.gif ||hotsashagrey.com^*/throated.jpg ||hotshame.com/hotshame_html/ ||hotshame.com/iframes/ ||hotshame.com/js/adphotshame ||hottestgirlsofmyspace.net/smallpics/300x200b.gif ||hottestgirlsofmyspace.net/smallpics/fb-150x150.gif ||hottubeclips.com/stxt/banners/ ||hungangels.com/vboard/friends/ ||hustler.com/backout-script/ ||imagearn.com/img/picBanner.swf ||imagecarry.com/down ||imagecarry.com/top ||imagedunk.com^*_imagedunk.js ||imagefruit.com^*/pops.js ||imagehyper.com/prom/ ||imageporter.com/ro-7bgsd.html ||imageporter.com/smate.html ||imagepost.com/includes/dating/ ||imagepost.com/stuff/ ||imageshack.us^*/bannng.jpg ||imagesnake.com/includes/js/cat.js ||imagesnake.com/includes/js/pops.js ||imagetwist.com/imagetwist*.js ||imagetwist.com/lj.js ||imgbabes.com/element.js ||imgbabes.com/ero-foo.html ||imgbabes.com/ja.html ||imgbabes.com^*/splash.php ||imgflare.com/exo.html ||imgflare.com^*/splash.php ||imghost.us.to/xxx/content/system/js/iframe.html ||imperia-of-hentai.net/banner/ ||indexxx.com^*/banners/ ||intporn.com^*/21s.js ||intporn.com^*/asma.js ||intporn.org/scripts/asma.js ||iseekgirls.com/g/pandoracash/ ||iseekgirls.com/js/fabulous.js ||iseekgirls.com/rotating_ ||iseekgirls.com^*/banners/ ||jailbaitgallery.com/banners300/ ||jav-porn.net/js/popout.js ||jav-porn.net/js/popup.js ||javsin.com/vip.html ||julesjordanvideo.com/flash/$object ||justporno.tv/ad/ ||kaotic.com^*/popnew.js ||keezmovies.com/iframe.html? ||kindgirls.com/banners2/ ||krasview.ru/content/$object ||krasview.ru/resource/a.php ||kuiken.co/inc/ex.js ||kuntfutube.com/kellyban.gif ||kyte.tv/flash/MarbachAdvertsDartInstream. ||laxtime.com/rotation/ ||lesbian.hu/banners/ ||linksave.in/fopen.html ||literotica.com/images/banners/ ||literotica.com/images/lit_banners/ ||live-porn.tv/adds/ ||liveandchat.tv/bana-/ ||livedoor.jp^*/bnr/bnr- ||lubetube.com/js/cspop.js ||lucidsponge.pl/pop_ ||lukeisback.com/images/boxes/ ||lukeisback.com^*/250.gif ||lw1.cdmediaworld.com^ ||m2.xhamster.com^ ||madmovs.com/rec/ ||madthumbs.com/madthumbs/sponsor/ ||mallandrinhas.net/flutuante ||matureworld.ws/images/banners/ ||maxjizztube.com/downloadfreemovies.php ||meatspin.com/facebookchatlist.php ||meatspin.com/images/fl.gif ||media1.realgfporn.com^$subdocument ||meendo.com/promos/ ||merb.ca/banner/ ||milkmanbook.com/dat/promo/ ||miragepics.com/images/11361497289209202613.jpg ||mobilepornmovies.com/images/banners/ ||monstercockz.com/cont/ ||monstercockz.com/eds/ ||monstertube.com/images/access_ ||monstertube.com/images/bottom-features.jpg ||monstertube.com/images/vjoin. ||monstertube.com/images/vjoin_ ||morazzia.com^*/banners/ ||morebabes.to/morebabes.js ||motherless.com/images/banners/ ||motherman.com/*.html ||mp3musicengine.com/bearshare_logo. ||mp3musicengine.com/images/freewatchtv1. ||mrskin.com/data/mrskincash/$third-party ||mrstiff.com/uploads/paysite/ ||mrstiff.com/view/context/ ||mrstiff.com/view/movie/bar/ ||mrstiff.com/view/movie/finished/ ||my-pornbase.com/banner/ ||mydailytube.com/nothing/ ||mygirlfriendvids.net/js/popall1.js ||myhentai.tv/popsstuff. ||myslavegirl.org/follow/go.js ||naked-sluts.us/prpop.js ||namethatpornstar.com/topphotos/ ||naughty.com/js/popJava.js ||naughtyblog.org/pr1pop.js ||netasdesalim.com/js/netas ||netronline.com/Include/burst.js ||newcelebnipslips.com/nipslipop.js ||niceyoungteens.com/ero-advertising ||niceyoungteens.com/mct.js ||nonktube.com/brazzers/ ||nonktube.com/nuevox/midroll.php? ||nonktube.com/popembed.js ||novoporn.com/imagelinks/ ||ns4w.org/gsm.js ||ns4w.org/images/promo/ ||ns4w.org/images/vod_ ||nude.hu/banners/ ||nudebabes.ws/galleries/banners/ ||nudevista.com/_/exo_ ||nudevista.com/_/pp. ||nudevista.com/_/teasernet ||nudography.com/photos/banners/ ||nuvid.com/videos_banner.html ||oasisactive.com^*/oasis-widget.html ||olderhill.com/ubr.js ||olderhill.com^*.html| ||onhercam.tv^*/banners/ ||onlinestars.net/ban/ ||onlinestars.net/br/ ||openjavascript.com/jtools/jads. ||oporn.com/js/wspop.js ||partners.xhamster.com^ ||pastime.biz/images/iloveint.gif ||pastime.biz/images/interracial-porn.gif ||pastime.biz^*/personalad*.jpg ||perfectgirls.net/b/ ||phncdn.com/cb/youpornwebfront/css/babes.css$domain=youporn.com ||phncdn.com/cb/youpornwebfront/css/skin.css$domain=youporn.com ||phncdn.com/css/campaign.css?$domain=pornhub.com ||phncdn.com/iframe ||phncdn.com/images/*_skin. ||phncdn.com/images/*_skin_ ||phncdn.com/images/banners/ ||phncdn.com/images/premium/ ||phncdn.com/images/premium_ ||phncdn.com/images/skin/ ||phncdn.com/mobile/js/interstitial-min.js? ||phun.org/phun/gfx/banner/ ||pichunter.com/creatives/ ||pichunter.com/deals/ ||picleet.com/inter_picleet.js ||picp2.com/img/putv ||picsexhub.com/js/pops. ||picsexhub.com/js/pops2. ||picsexhub.com/rec/ ||picturedip.com/modalfiles/modal.js ||picturedip.com/windowfiles/dhtmlwindow.css ||picturescream.com/porn_movies.gif ||picturescream.com/top_banners.html ||picturevip.com/imagehost/top_banners.html ||picxme.com/js/pops. ||picxme.com/rec/ ||pimpandhost.com/images/pah-download.gif ||pimpandhost.com/static/html/iframe.html ||pimpandhost.com/static/i/*-pah.jpg ||pink-o-rama.com/Blazingbucks ||pink-o-rama.com/Brothersincash ||pink-o-rama.com/Fetishhits ||pink-o-rama.com/Fuckyou ||pink-o-rama.com/Gammae ||pink-o-rama.com/Karups ||pink-o-rama.com/Longbucks/ ||pink-o-rama.com/Nscash ||pink-o-rama.com/Pimproll/ ||pink-o-rama.com/Privatecash ||pink-o-rama.com/Royalcash/ ||pink-o-rama.com/Teendreams ||pinkems.com/images/buttons/ ||pinkrod.com/iframes/ ||pinkrod.com/js/adppinkrod ||pinkrod.com/pinkrod_html/ ||pixhost.org/image/cu/ ||pixhost.org/image/rotate/ ||pixhost.org/js/jquery_show2.js ||pixroute.com/spl.js ||placepictures.com/Frame.aspx? ||planetsuzy.org/kakiframe/ ||playgirl.com/pg/media/prolong_ad.png ||plumper6.com/images/ban_pp.jpg ||pnet.co.za/jobsearch_iframe_ ||poguide.com/cdn/images/ad*.gif ||pontoperdido.com/js/webmessenger.js ||porn-w.org/images/chs.gif ||porn-w.org/images/cosy/ ||porn-w.org/images/zevera.png ||porn.com/assets/partner_ ||porn.com/js/pu.js ||porn4down.com^*/ryuvuong.gif ||porn8x.net/js/outtrade.js ||porn8x.net/js/popup.js ||pornalized.com/contents/content_sources/ ||pornalized.com/js/adppornalized5.js ||pornalized.com/pornalized_html/closetoplay_ ||pornarchive.net/images/cb ||pornbanana.com/pornbanana/deals/ ||pornbay.org/popup.js ||pornbb.org/adsnov. ||pornbb.org/images/rotation/$image ||pornbus.org/includes/js/bgcont.js ||pornbus.org/includes/js/cat.js ||pornbus.org/includes/js/ex.js ||pornbus.org/includes/js/exa.js ||pornbus.org/includes/js/layer.js ||porncor.com/sitelist.php ||pornerbros.com/p_bnrs/ ||pornerbros.com/rec/$subdocument ||pornfanplace.com/js/pops. ||pornfanplace.com/rec/ ||pornhub.com/catagories/costume/ ||pornhub.com/channels/pay/ ||pornhub.com/front/alternative/ ||pornhub.com/jpg/ ||pornhub.com/pics/latest/$xmlhttprequest ||pornhub.com^$script,domain=pornhub.com ||pornhub.com^$subdocument,~third-party ||pornhub.phncdn.com/images/campaign-backgrounds/ ||pornhub.phncdn.com/misc/xml/preroll.xml ||pornizer.com/_Themes/javascript/cts.js? ||pornmade.com/images/404vz.gif ||pornmade.com/images/az.gif ||pornmade.com/images/cb ||pornnavigate.com/feeds/delivery.php? ||pornoid.com/contents/content_sources/ ||pornoid.com/iframes/bottom ||pornoid.com/js/adppornoid ||pornoid.com/pornoid_html/ ||pornoinside.com/efpop.js ||pornomovies.com/js/1/login_bonus ||pornomovies.com/pop/ ||pornorips.com/hwpop.js ||pornorips.com^*/rda.js ||pornorips.com^*/rotate*.php ||pornosexxxtits.com/rec/ ||pornoxo.com/pxo/$subdocument ||pornoxo.com/tradethumbs/ ||pornper.com/mlr/ ||pornper.com^*/pp.js ||pornreleasez.com/prpop.js ||pornshare.biz/1.js ||pornshare.biz/2.js ||pornsharia.com/Images/Sponsors/ ||pornsharia.com^*/adppornsharia.js ||pornsharia.com^*/exo- ||pornsharia.com^*/js/pcin.js ||pornsharing.com/App_Themes/pornsharianew/$subdocument,~third-party ||pornsharing.com/App_Themes/pornsharianew/js/adppornsharia*.js ||pornsharing.com/App_Themes/pornsharingnew/$subdocument,~third-party ||pornsharing.com/App_Themes/pornsharingnew/js/adppornsharia*.js ||pornslash.com/images/a.gif ||pornslash.com/images/cbside.gif ||pornslash.com/images/cbt.gif ||pornslash.com/images/downicon.png ||pornslash.com/images/pr.jpg ||pornstarlabs.com/spons/ ||pornstarterritory.com//images/bannernew.jpg ||pornstarterritory.com^*/alsbanner ||pornstreet.com/siteunder.js ||porntalk.com/img/banners/ ||porntalk.com/rec/ ||porntube.com/ads| ||pornup.me/js/pp.js ||pornvideoxo.com^$subdocument,~third-party ||pornwikileaks.com/adultdvd.com.jpg ||pr-static.empflix.com^ ||pr-static.tnaflix.com^ ||pureandsexy.org/banner/ ||purelynsfw.com^*/banners/ ||purepornvids.com/randomadseb. ||purpleporno.com/pop*.js ||putascaseiras.com/botao/ ||puteros.com/publisecciones/ ||pwpwpoker.com/images/*/strip_poker_ ||pwpwpoker.com/images/banners/ ||r.radikal.ru^ ||raincoatreviews.com/images/banners/ ||realgfporn.com/js/popall.js ||realgfporn.com/js/realgfporn.js ||realhomesex.net/*.html$subdocument ||realhomesex.net/ae/$subdocument ||realhomesex.net/floater.js ||realhomesex.net/pop/ ||redtube.cc/images/bongacams.png ||redtube.com/barelylegal/ ||redtube.com/bestporn/ ||redtube.com/nymphos/ ||redtube.com/sexychicks/ ||redtube.com/wierd/ ||redtube.com^$subdocument,~third-party ||redtube.com^*/banner/ ||redtubefiles.com^*/banner/ ||redtubefiles.com^*/skins/ ||rev.fapdu.com^ ||rextube.com/plug/iframe.asp? ||rikotachibana.org/wp-content/banner/ ||rude.com/js/PopupWindow.js ||rusdosug.com/Fotos/Banners/ ||s.xvideos.com^$subdocument ||scorehd.com/banner/ ||scorevideos.com/banner/ ||seaporn.org/scripts/life.js ||seemygf.com/webmasters/ ||sensualgirls.org/banner/ ||sensualgirls.org/media/banners/ ||serveporn.com/images/a-en.jpg ||serveporn.com/images/plug-in.jpg ||sex-techniques-and-positions.com/123ima/ ||sex-techniques-and-positions.com/banners ||sex.com/images/*/banner_ ||sex3.com/if/ ||sex3dtoons.com/im/ ||sexilation.com/wp-content/uploads/2013/01/Untitled-1.jpg ||sexmummy.com/float.htm ||sexmummy.com/footer.htm ||sexseeimage.com^*/banner.gif ||sextube.com/lj.js ||sextubebox.com/ab1.shtml ||sextubebox.com/ab2.shtml ||sexuhot.com/images/xbanner ||sexvines.co/images/cp ||sexy-toons.org/interface/partenariat/ ||sexy-toons.org/interface/pub/ ||sexyandfunny.com/images/totem ||sexyandshocking.com/mzpop.js ||sexyclips.org/banners/ ||sexyclips.org/i/130x500.gif ||sexyfuckgames.com/images/promo/ ||sexyshare.net//banners/ ||sexytime.com/img/sexytime_anima.gif ||shanbara.jp/300_200plus.jpg ||shanbara.jp/okusamadx.gif ||sharew.org/modalfiles/ ||shooshtime.com/ads/ ||shooshtime.com/images/chosenplugs/ ||shooshtimeinc.com/under.php ||shy-cams.com/tube.js ||signbucks.com/s/bns/ ||signbucksdaily.com/data/promo/ ||sillusions.ws^*/pr0pop.js ||sillusions.ws^*/vpn-banner.gif ||site.img.4tube.com^ ||skimtube.com/kellyban.gif ||slinky.com.au/banners/ ||smutmodels.com/sponsors/ ||socaseiras.com.br/arquivos/banners/ ||socaseiras.com.br/banner_ ||socaseiras.com.br/banners.php? ||songs.pk/ie/ietext.html ||spankbang.com/gateway/ ||springbreaktubegirls.com/js/springpop.js ||starcelebs.com/logos/$image ||static.flabber.net^*background ||static.kinghost.com^ ||stockingstv.com/partners/ ||stolenvideos.net/stolen.js ||submityourflicks.com/banner/ ||svscomics.com^*/dtrotator.js ||sxx.com/js/lj.js ||t8.*.com/?*_|$xmlhttprequest,domain=tube8.com ||taxidrivermovie.com/mrskin_runner/ ||teensanalfactor.com/best/ ||teensexcraze.com/awesome/leader.html ||teentube18.com/js/realamateurtube.js ||temptingangels.org/banner/ ||temptingangels.org/media/banners/ ||the-analist.info^*150-150 ||the-analist.info^*150sq ||the-analist.info^*150x150 ||the-feeding-tube.com^*/Topbanner.php ||thedoujin.com^$domain=gelbooru.com ||thehun.net^*/banners/ ||thenewporn.com/js/adpthenewporn ||thenipslip.com/GGWDrunkenAd.jpg ||thenipslip.com/mfcbanner.gif ||theporncore.com/contents/content_sources/ ||thepornomatrix.com/images/1- ||thinkexist.com/images/afm.js ||thisav.com/js/thisav_pop.js ||thumblogger.com/thumblog/top_banner_silver.js ||timtube.com/traffic.js ||titsintops.com/intersitial/ ||titsintops.com/rotate/ ||tjoob.com/bgbb.jpg ||tjoob.com/kellyban.gif ||tnaflix.com/banner/ ||tnaflix.com/flixPlayerImages/ ||tnaflix.com^*_promo.jpg ||trovaporno.com/image/incontri$image ||tube8.com/penthouse/ ||tube8.com/sugarcrush/ ||tube8.com^$subdocument,~third-party ||tubedupe.com/footer_four.html ||tubedupe.com/side_two.html ||turboimagehost.com/p1.js ||twinsporn.net/images/delay.gif ||twinsporn.net/images/free-penis-pills.png ||twofuckers.com/brazzers ||uflash.tv^*/affiliates/ ||ukrainamateurs.com/images/banners/ ||unblockedpiratebay.com/static/img/bar.gif ||unoxxx.com/pages/en_player_video_right.html ||updatetube.com/js/adpupdatetube ||vibraporn.com/vg/ ||vid2c.com/js/atxpp.js? ||vid2c.com/js/pp.js ||vid2c.com/pap.js ||vid2c.com/pp.js ||videarn.com/vibrate.js ||videos.com^*/jsp.js ||vidgrab.net/adsbar.png ||vidgrab.net/bnr.js ||vidgrab.net/images/adsbar ||vidgrab.net/pads2.js ||viralporn.com^*/popnew.js ||vstreamcdn.com^*/ads/ ||wank.to/partner/ ||wankspider.com/js/wankspider.js ||watch2porn.net/pads2.js ||watchindianporn.net/js/pu.js ||weberotic.net/banners/ ||wegcash.com/click/ ||wetplace.com/iframes/$subdocument ||wetplace.com/js/adpwetplace ||wetplace.com/wetplace_html/ ||wetpussygames.com/images/promo/ ||whitedolly.com/wcf/images/redbar/logo_neu.gif ||whozacunt.com/images/*-300x250. ||whozacunt.com/images/*_300x200_ ||whozacunt.com/images/banner_ ||wiki-stars.com/thumb_if.php? ||wiki-stars.com/trade/ ||wikiporno.org/header2.html ||worldsex.com/c/ ||wowomg.com/*.html ||wrenchtube.com/poppt.js ||wunbuck.com/_odd_images/banners/ ||wunbuck.com/iframes/aaw_leaderboard.html ||x3xtube.com/banner_rotating_ ||xbabe.com/iframes/ ||xbooru.com/block/adblocks.js ||xbutter.com/adz.html ||xbutter.com/geturl.php/ ||xbutter.com/js/pop-er.js ||xfanz.com^*_banner_ ||xhamster.com/ads/ ||xhamster.com/js/xpu.js ||xhamsterpremiumpass.com/premium_scenes.html ||xhcdn.com^*/ads_ ||xogogo.com/images/latestpt.gif ||xtravids.com/pop.php ||xvideohost.com/hor_banner.php ||xxvideo.us/ad728x15 ||xxvideo.us/bnr.js ||xxvideo.us/playertext.html ||xxxblink.com/js/pops. ||xxxblink.com/rec/ ||xxxfile.net^*/netload_premium.gif ||xxxgames.biz^*/sponsors/ ||xxxkinky.com/pap.js ||xxxlinks.es/xvideos.js ||xxxporntalk.com/images/ ||xxxxsextube.com/*.html$subdocument ||xxxymovies.com/js/win.js ||yobt.com/rec/ ||yobt.tv/js/ttu.js ||yobt.tv/rec/ ||youaresogay.com/*.html ||youjizz.com/vivid/ ||youngpornvideos.com/images/bangbros/ ||youngpornvideos.com/images/glamglam/ ||youngpornvideos.com/images/mofoscash/ ||youngpornvideos.com/images/teencash/ ||youngpornvideos.com/images/webmasterdelightlinks/ ||youngpornvideos.com/images/wmasterthecoolporn/ ||youporn-hub.com/lcdscript.js ||youporn-hub.com/newlcd.js ||youporn.com/capedorset/ ||youporn.com/watch_postroll/ ||youporn.com^$script,domain=youporn.com ||youporn.com^$script,subdocument,domain=youporngay.com ||youporn.com^$subdocument,~third-party ||yourdailygirls.com/vanilla/process.php ||yourdarkdesires.com/1.html ||yourdarkdesires.com/2.html ||yourdarkdesires.com/3.html ||yourlust.com/im/onpause.html ||yourlust.com/im/postroll.html ||youtubelike.com/ftt2/toplists/ ||youx.xxx/thumb_top/ ||yporn.tv/uploads/flv_player/commercials/ ||yporn.tv/uploads/flv_player/midroll_images/ ||yumymilf.com^*/banners/ ||yuvutu.com^*/banners/ ||zazzybabes.com/misc/virtuagirl-skin.js ! *** easylist:easylist_adult/adult_specific_block_popup.txt *** ^utm_medium=pops^$popup,domain=ratedporntube.com|sextuberate.com |http://*?*=$popup,third-party,domain=extremetube.com|pornhub.com|redtube.com|spankwire.com|tube8.com|youporn.com|youporngay.com |http://*?*^id^$popup,third-party,domain=extremetube.com|pornhub.com|redtube.com|spankwire.com|tube8.com|youporn.com|youporngay.com ||ad.userporn.com^$popup ||eporner.com/pop.php$popup ||fantasti.cc^*?ad=$popup ||fantastube.com/track.php$popup ||fc2.com^$popup,domain=xvideos.com ||fileparadox.in/free$popup,domain=tdarkangel.com ||h2porn.com/pu.php$popup ||hegansex.com/exo.php$popup ||heganteens.com/exo.php$popup ||imagebam.com/redirect_awe.php$popup ||movies.askjolene.com/c64?clickid=$popup ||namethatporn.com/ntpoo$popup ||pinporn.com/popunder/$popup ||pop.fapxl.com^$popup ||pop.mrstiff.com^$popup ||porn101.com^$popup,domain=lexsteele.com ||porn4free.tv^$popup,domain=redtube.cc ||pornuppz.info/out.php$popup ||publicagent.com/bigzpup.php$popup ||rackcdn.com^$popup,domain=extremetube.com|pornhub.com|redtube.com|spankwire.com|tube8.com|youporn.com|youporngay.com ||site-rips.org^$popup,domain=backupload.net ||ymages.org/prepop.php$popup !------------------------Specific element hiding rules------------------------! ! *** easylist:easylist/easylist_specific_hide.txt *** search.safefinder.com,search.snapdo.com###ABottomD aol.com###AOLP_partnerSearch search.safefinder.com,search.snap.do,search.snapdo.com###ATopD avsforum.com###AVSForum_com_300x150_Sponsor_TECH_Forum patheos.com###A_Artl_970x90_OptDirect patheos.com###A_Home_728x90_Header el33tonline.com###AdB nextag.com###AdBox el33tonline.com###AdC community.adlandpro.com###AdContent el33tonline.com###AdD el33tonline.com###AdE el33tonline.com###AdF el33tonline.com###AdG el33tonline.com###AdH el33tonline.com###AdI el33tonline.com###AdK el33tonline.com###AdL rosemaryconley.tv###Add igcd.net,tangorin.com,webcarstory.com###Ads search.snap.do,search.snapdo.com###AfloatingD kbb.com###Aside knowyourmoney.co.uk###Au_HomePage350x200 fileresearchcenter.com###AutoNumber3 crictime.com###AutoNumber5 buzzfeed.com###BF_WIDGET_10 novafm.com.au###BGLink ebuddy.com###Banner weegy.com###BannerDiv arto.com###BannerInfobox muchmusic.com###BigBox slice.ca###BigBoxContainer metacafe.com###Billboard whatsupiran.com###BottomBanner foodnetwork.ca###BottomLeader advfn.com###BottomTabsElement montereyherald.com###BreakingNewsSponsor marketwatch.com###BrokerButtons ebuddy.com###Button cgsociety.org###CGS_home_900 canoe.ca###CanoeBigBoxAd answers.com###Casale_300x250_wrapper citytv.com###CityTv-HeaderBannerBorder ynetnews.com###ClarityRayButton naturalnews.com###Container-Tier1 naturalnews.com###Container-Tier2 supersport.com###ContentPlaceHolder1_featureShopControl1_shop cardomain.com###ContentPlaceHolder1_rideForSaleOnEbay supersport.com###ContentPlaceHolder1_shop1_shopDiv muchmusic.com###ContestsSide uinterview.com###CrowdIgnite amazon.com###DAadrp ibtimes.com###DHTMLSuite_modalBox_contentDiv gamesforgirlz.net###DUL-jack msn.com###Dcolumn merriam-webster.com###Dictionary-MW_DICT_728_BOT starcanterbury.co.nz###DivBigBanner meettheboss.tv###DivCenterSpaceContainer nzherald.co.nz###DivContentRect nzherald.co.nz###DivHeadlineRect hollywood.com###DivSkyscraper wackyarchives.com###Div_b wackyarchives.com###Div_s cdcovers.cc###EBTopBanner englishclub.com###ECtopLB javaprogrammingforums.com###EG6209c8f52f7d41a397438a16159bb58e marthastewart.com###ERA_AD_BLOCK1 nzherald.co.nz###ExtendedBanner keprtv.com###FIN_300x250-600_homepage keprtv.com###FIN_dc_300x250_home behance.net###FMGABadge hothardware.com###FillerLeftLink hothardware.com###FillerRightLink blackamericaweb.com,camfuze.com###FooterBanner liverpoolfc.com###FooterLogos wlup.com###FooterOpenX eweek.com###Form1 formspring.me###Formspringme_Profile_300x250 stayontheblack.com###GAdvert financialsurvivalnetwork.com,tsbmag.com###GB_overlay financialsurvivalnetwork.com,tsbmag.com###GB_window writersdigest.com###GLinks gajitz.com###Gajitz-300x250 humorpix.com###GoogleSidebarRight infoplease.com###HCads wikia.com,wowwiki.com###HOME_LEFT_SKYSCRAPER_1 wikia.com,wowwiki.com###HOME_TOP_LEADERBOARD theweek.com###HPLeaderbox myoutsourcedbrain.com###HTML2 celebnipslipblog.com,countryweekly.com###HeaderBanner greatschools.org###Header_728x90 myspace.com###HeroUnitMedRec dreamteamfc.com###HomeContentMpu austinchronicle.com###HowAboutWe collegerecruiter.com###IMU_468x60 collegerecruiter.com###IMU_468x60_search-results collegerecruiter.com###IMU_728x90 patheos.com###I_Artl_970x40_Breaking patheos.com###I_Blog_300x100_Pos1 icelandreview.com###ImgArea2 serverwatch.com###InlineAssetListing indiaresults.com###Irc_Gra_add khaleejtimes.com###KTBannerBox ign.com###LB_Row globaltv.com###LBigBox wikia.com,wowwiki.com###LEFT_SKYSCRAPER_1 wikia.com###LEFT_SKYSCRAPER_2 yahoo.com###LREC stupidvideos.com###LRECContainer livesoccertv.com###LSTV_ROS_300x250 livesoccertv.com###LSTV_ROS_468x60 mb.com.ph###LeaderBoardTop muchmusic.com###Leaderboard wistechnology.com###LeaderboardContainer freeiconsdownload.com###LeftBanner printmag.com,wetcanvas.com###LinkSpace ustream.tv###LoginBannerWrapper hotnewhiphop.com###LookoutContent mail.yahoo.com###MIP4 medicalnewstoday.com###MNT_600xFlex_Middle mail.yahoo.com###MNW autotrader.ie,natgeotv.com###MPU nick.co.uk###MPU-wrap moneyexpert.com###MPUBanner yahoo.com###MREC entrepreneur.com.ph###MREC01 entrepreneur.com.ph###MREC02 i4u.com###MainContent > .SidebarBox uinterview.com###MarketGid2421 free-torrents.org###MarketGid900 investopedia.com###Marketplace metacafe.com###MedRect metacafe.com###MedRect2 howstuffworks.com###MedRectHome finance.yahoo.com,news.yahoo.com###MediaFeaturedListEditorial facebook.com###MessagingNetegoWrapper tokeofthetown.com,toplessrobot.com###Middle nytimes.com###MiddleRight apcointl.org###Mod124 thetibetpost.com###Mod277 thetibetpost.com###Mod296 theoslotimes.com###Mod346 kbb.com###Mrec-container ninemsn.com.au###NH_shoppingTabs nytimes.com###NYTD_DYNAMIC_IFADS kbb.com###New-spotlights india.com###NewBanner walmart.com###OAS_Left1 vidspot.net###On3Pla1ySpot bestreams.net,fastvideo.in,played.to,realvid.net,vidstream.in###OnPlayerBanner allmyvideos.net###OnPlayerClose pch.com###PCHAdWrap missoulian.com,thenewstribune.com,theolympian.com###PG_fb azdailysun.com,azstarnet.com,billingsgazette.com,elkodaily.com,heraldextra.com,metromix.com,missoulian.com,tdn.com,thenewstribune.com,theolympian.com,trib.com###PG_link joystickdivision.com###Page_Header clipmarks.com###Panel politicususa.com###PrimaryMid1 dinodirect.com###ProductShowAD newser.com###PromoSquare globaltv.com###RBigBoxContainer gardenista.com,remodelista.com###REMODELISTA_BTF_CENTER_AD_FRAME gardenista.com,remodelista.com###REMODELISTA_BTF_RIGHTRAIL-2 smash247.com###RT1 readwriteweb.com###RWW_BTF_CENTER_AD istockanalyst.com###RadWindowWrapper_ctl00_ContentPlaceHolderMain_registration awazfm.co.uk###Recomends ebuddy.com###Rectangle reference.com###Resource_Center blackamericaweb.com###RightBlockContainer2 killsometime.com###RightColumnSkyScraperContainer mail.yahoo.com,skateboardermag.com###SKY globaltv.com###SPBigBox globaltv.com###SRBigBoxContainer msn.com###Sales1 msn.com###Sales2 msn.com###Sales3 msn.com###Sales4 scamdex.com###ScamdexLeaderboard medicinenet.com###SearchUnit polyvore.com###Set_RHS_IABMediumRect in.msn.com###Shaadi triblive.com###ShopLocal whitepages.ae###ShortRectangle_UpdatePanel2 grapevine.is###Side mail.aol.com###SidePanel msnbc.msn.com,nbcnews.com###Sidebar2-sponsored daringfireball.net###SidebarTheDeck imcdb.org###SiteLifeSupport imcdb.org###SiteLifeSupportMissing thisismoney.co.uk###Sky austinchronicle.com###Skyscraper teoma.com###Slink writersdigest.com###SpLinks howstuffworks.com###SponLogo rapidsharedata.com###Sponsored similarsites.com###SponsoredTag gamebanana.com###SquareBanner linuxjournal.com###TB_overlay linuxjournal.com###TB_window ninemsn.com.au###THEFIX_promo wikia.com,wowwiki.com###TOP_LEADERBOARD ustream.tv###Takeover glasssteelandstone.com###TextSponsorBar joystickdivision.com,tokeofthetown.com,toplessrobot.com###Top blackamericaweb.com,cjnews.com,entertainmentearth.com###TopBanner gamespy.com###TopMedRec governing.com###Topbanner genengnews.com###Topbanner_bar al.com###Toprail_Leaderboard gamebanana.com###TowerBanner austinchronicle.com###TravelZoo xe.com###UCCInputPage_Slot1 xe.com###UCCInputPage_Slot2 xe.com###UCCInputPage_Slot3 globaltv.com###VideoPlayer-BigBox moviefone.com###WIAModule rediff.com###WR1_container albumjams.com,ecostream.tv###WarningCodec wikia.com###WikiaTopAds xojane.com###XOJANE_BTF_CENTER xojane.com###XOJANE_BTF_RIGHTRAIL nytimes.com###XXL music.yahoo.com###YMusicRegion_T2_R2C2 music.yahoo.com###YMusicRegion_T3_R2C2_R1 music.yahoo.com###YMusicRegion_TN1_R2C2_R1 yahoo.com###YSLUG zapak.com###ZAPADS_Middle golf.com###\31 000-104-ros gearburn.com,memeburn.com###\33 00X250ad tvembed.eu###\33 00banner dangerousminds.net###\37 28ad forexpros.com###\5f 300x250textads thegalaxytabforum.com###\5f _fixme happystreams.net###\5f ad_ funnyordie.com###\5f ad_div mail.google.com###\:rr .nH[role="main"] .mq:first-child mail.google.com###\:rr > .nH > .nH[role="main"] > .aKB mail.google.com###\:rr > .nH > .nH[role="main"] > .nH > .nH > .AT[style] mail.google.com###\:rr > .nH > div[role="main"] > .mq:last-child business.com###_ctl0_RightContentplaceholder_FeaturedListingsUC_featuredListingsBox ama-assn.org###a dm5.com###a1 anchorfree.net###a72890_1 metblogs.com###a_medrect ytmnd.com###a_plague_upon_your_house metblogs.com###a_widesky ipdb.at###aaa totalfilm.com###ab1 webgurubb.com###ab_top nearlygood.com###abf unblock-proxy-server.com###ablc jakeludington.com###ablock jakeludington.com###ablock3 free-tv-video-online.me###ablocker federalnewsradio.com###above-header-980 next-gen.biz###above-header-region blekko.com###above-results > #number-results + div macworld.com###aboveFootPromo healthgrades.com###abovePage feministing.com###abovefooter feministing.com###aboveheader tvseriesfinale.com###abox reference.com,thesaurus.com###abvFold blocked-website.com###acbox filefactory.com###acontainer bitcoca.com###active1 bitcoca.com###active2 bitcoca.com###active3 1050talk.com,4chan.org,altervista.org,amazon.com,aol.com,ap.org,awfuladvertisements.com,bitcoinmonitor.com,braingle.com,campusrn.com,chicagonow.com,cocoia.com,cryptoarticles.com,dailydigestnews.com,daisuki.net,devshed.com,djmickbabes.com,drakulastream.eu,earthtechling.com,esquire.com,fantom-xp.com,farmville.com,fosswire.com,fullrip.net,g4tv.com,gifts.com,golackawanna.com,google.com,guiminer.org,helpwithwindows.com,hknepaliradio.com,ifunnyplanet.com,ifyoulaughyoulose.com,imageshack.us,instapaper.com,internetradiouk.com,investorschronicle.co.uk,jamaicaradio.net,jamendo.com,jigzone.com,learnhub.com,legendofhallowdega.com,libertychampion.com,livevss.net,loveshack.org,lshunter.tv,macstories.net,marketingpilgrim.com,mbta.com,milkandcookies.com,msn.com,msnbc.com,mydallaspost.com,nbcnews.com,neoseeker.com,nepaenergyjournal.com,ninemsn.com.au,nzherald.co.nz,omgili.com,onlineradios.in,phonezoo.com,printitgreen.com,psdispatch.com,psu.com,queensberry-rules.com,radio.net.bd,radio.net.pk,radio.or.ke,radio.org.ng,radio.org.nz,radio.org.ph,radioonline.co.id,radioonline.my,radioonline.vn,radiosa.org,radioth.net,radiowebsites.org,rapidshare-downloads.com,reversegif.com,robotchicken.com,saportareport.com,sciencerecorder.com,shop4freebies.com,slidetoplay.com,socialmarker.com,statecolumn.com,streamhunter.eu,technorati.com,theabingtonjournal.com,thetelegraph.com,timesleader.com,torrentbutler.eu,totaljerkface.com,totallycrap.com,trinidadradiostations.net,tutorialized.com,twitch.tv,ultimate-rihanna.com,vetstreet.com,vladtv.com,wallpapers-diq.com,wefunction.com,womensradio.com,xe.com,yahoo.com,youbeauty.com,ytconv.net,zootool.com###ad clip.dj,dafont.com,documentary.net,gomapper.com,idahostatejournal.com,investorschronicle.co.uk,megafilmeshd.net,newsinc.com,splitsider.com,theawl.com,thehindu.com,thehindubusinessline.com,timeanddate.com,troyhunt.com,weekendpost.co.zw,wordreference.com###ad1 btvguide.com,cuteoverload.com,edmunds.com,investorschronicle.co.uk,megafilmeshd.net,pimpandhost.com,theawl.com,thehairpin.com,troyhunt.com,weekendpost.co.zw###ad2 btvguide.com,internetradiouk.com,jamaicaradio.net,onlineradios.in,pimpandhost.com,radio.net.bd,radio.net.pk,radio.or.ke,radio.org.ng,radio.org.nz,radio.org.ph,radioonline.co.id,radioonline.my,radioonline.vn,radiosa.org,radioth.net,splitsider.com,theawl.com,thehairpin.com,trinidadradiostations.net,way2sms.com,weekendpost.co.zw,zerocast.tv###ad3 splitsider.com,theawl.com,thehairpin.com###ad4 about.com,allexperts.com###adB joblo.com###adBillboard fxnetworks.com,isearch.avg.com###adBlock experts-exchange.com###adComponent gamemazing.com###adContainer about.com,paidcontent.org###adL apnadesi-tv.net,britsabroad.com,candlepowerforums.com,droidforums.net,filesharingtalk.com,forum.opencarry.org,gsmindore.com,hongfire.com,justskins.com,kiwibiker.co.nz,lifeinvictoria.com,lotoftalks.com,m-hddl.com,moneymakerdiscussion.com,mpgh.net,nextgenupdate.com,partyvibe.com,perthpoms.com,pomsinadelaide.com,pomsinoz.com,printroot.com,thriveforums.org,watchdesitv.com,watchuseek.com,webmastertalkforums.com,win8heads.com###ad_global_below_navbar im9.eu###adb tweakguides.com###adbar > br + p[style="text-align: center"] + p[style="text-align: center"] tweakguides.com###adbar > br + p[style="text-align: center"] + p[style="text-align: center"] + p phonezoo.com###adbb mp3tag.de###adblock-download nowsci.com###adblocker bizjournals.com###adc2 rapid-search-engine.com###adcid1 fotochatter.com###adcon tubeplus.me###add pbs.org###add-block-placer neurosoftware.ro###addDiv atlanticfarmfocus.ca###add_bottom imageshack.us###add_frame canadianfamily.ca###add_left canadianfamily.ca###add_right chipchick.com###add_space577 atlanticfarmfocus.ca,capebretonpost.com,paherald.sk.ca###add_top washingtonjewishweek.com###addclose veryicon.com###addd barbavid.com###additional_plugins_bar way2sms.com###addiv joymag.co.za###addlink torrent-finder.info###addon_info computerworld.com###addresources computerworld.com###addresources_module kenrockwell.com,mocospace.com,telegraph.co.uk###adds chronicleonline.com,sentinelnews.com,theandersonnews.com###adgallery tortoisesvn.net###adgroup shivtr.com###admanager girlsgames.biz###admd mp3skull.com###adr_banner mp3skull.com###adr_banner_2 909lifefm.com,anichart.net,audioreview.com,carlow-nationalist.ie,chelseanews.com,daemon-tools.cc,disconnect.me,dreadcentral.com,duckduckgo.com,eveningecho.ie,financenews.co.uk,footballfancast.com,g.doubleclick.net,gearculture.com,genevalunch.com,hdcast.tv,healthboards.com,hiphopisdream.com,inspirationti.me,isearch-for.com,kildare-nationalist.ie,laois-nationalist.ie,lorempixel.com,lyricstime.com,mobilerevamp.org,mtbr.com,nylonguysmag.com,photographyreview.com,placehold.it,playr.org,privack.com,quiz4fun.com,quote.com,roscommonherald.ie,skyuser.co.uk,talk1300.com,theindustry.cc,toorgle.net,triblive.com,tvope.com,urbandictionary.com,washingtonmonthly.com,waterford-news.ie,wccftech.com,westernpeople.com,wexfordecho.ie###ads release-ddl.com,womanowned.com###ads3 chia-anime.com###ads4 chia-anime.com###ads8 screencity.pl###ads_left privack.com###adsb boingboing.net###adskin videos.com###adsl smh.com.au###adspot-300x600\,300x250-pos-1 videos.com###adst fitnessmagazine.com###adtag ninemsn.com.au###adtile conservativepost.com###adtl mnn.com,streamtuner.me###adv novamov.com,tinyvid.net,videoweed.es###adv1 cad-comic.com###advBlock forexminute.com###advBlokck teleservices.mu###adv_\'146\' arsenal.com,farmersvilletimes.com,ishared.eu,murphymonitor.com,princetonherald.com,runescape.com,sachsenews.com,shared2.me,wylienews.com###advert uploaded.to###advertMN bt.com,chron.com,climateprogress.org,computingondemand.com,everydaydish.tv,fisher-price.com,funnygames.co.uk,games.on.net,givemefootball.com,intoday.in,iwin.com,msn.com,mysanantonio.com,nickjr.com,nytsyn.com,opry.com,peoplepets.com,psu.com,radiozdk.com,sonypictures.com,thatsfit.com,truelocal.com.au,unshorten.it,variety.com,washingtonian.com,yippy.com###advertisement typepad.com###advertisements miamisunpost.com###advertisers bom.gov.au,develop-online.net,geeky-gadgets.com,govolsxtra.com,hwbot.org,motortorque.com,pcr-online.biz,profy.com,webshots.com###advertising 1cookinggames.com,intowindows.com,irishhealth.com,playkissing.com,snewscms.com,yokogames.com###advertisment kickoff.com###advertisng share-links.biz###advice sofeminine.co.uk###af_lmbcol_sep katzforums.com###aff zap2it.com###aff_rightbar nigeriafootball.com###affiliate-bottom gtopala.com###affiliate-index-300x250 carmall.com###affiliates awkwardfamilyphotos.com###afpadq-leaderboard awkwardfamilyphotos.com###afpadq-sidebar1 awkwardfamilyphotos.com###afpadq-sidebar2 search.rr.com###afsBot search.rr.com###afsTop investorplace.com###after-post-banner allgames.com###ag_AdBannerTop aol.com###ai300x250 ajchomefinder.com###ajc-homefinder-leaderboard unknown-horizons.org###akct news.com.au###alert-strap luckyacepoker.com###alertpop release-ddl.com###alexa search.mywebsearch.com###algo + div[id] search.mywebsearch.com###algo + div[id] + div[id] blisstree.com,mommyish.com,teen.com,thegloss.com,thegrindstone.com###alloy-300x250-tile2 teen.com###alloy-300x250-tile3 gurl.com,teen.com###alloy-728x90-tile1 gurl.com,teen.com###alloy-728x90-tile4 ohjoy.blogs.com###alpha ohjoy.blogs.com###alpha-inner alternet.org###altsocial_splash sportsgrid.com,thejanedough.com###am-ngg-ss-unit-label 3dtin.com,juicefm.com,ovguide.com,pulse1.co.uk,pulse2.co.uk,signal1.co.uk,signal2.co.uk,swanseasound.co.uk,thewave.co.uk,wave965.com,wbur.org,wirefm.com,wishfm.net###amazon imdb.com###amazon-affiliates pri.org###amazonBox180 pcadvisor.co.uk###amazonPriceListContainer imfdb.org###amazoncontent zap2it.com###amc-twt-module realbeauty.com###ams_728_90 publicradio.org###amzContainer aim.org###amznCharityBanner visitsundsvall.se###annons-panel hardocp.com###announcements peliculas-flv.com###anuncio dailymirror.lk###apDiv2 > .main > div[style="margin:5px 0 0px 0;"] topix.com###apartments_block publicradio.org###apm_sponsor cultofmac.com###apptapArticleBottom bizjournals.com###arcbc1 archlinux.org###arch-sponsors boingboing.net###ards philly.com###area-main-center-road-block moneynews.com###artPgScnShrWrapper independent.co.uk###article > .box ighome.com###article-modal + div[style="margin:0 25px;"] > .gadget-box[width="100%"]:first-child:last-child eveningtimes.co.uk###article-mpu wtkr.com###article-promo adotas.com,radiotimes.com###article-sponsor london24.com###article-top accountingtoday.com,themiddlemarket.com###article_bigbox computerworld.com.au###article_whitepapers gethampshire.co.uk###articleright findmysoft.com###as_336 vortez.net###aseadnetv2 flyordie.com###asf ktar.com###askadv autoblog.com###asl_bot autoblog.com###asl_top pv-tech.org###associations-wrapper forwardprogressives.com###aswift_1_expand forwardprogressives.com###aswift_2_expand forwardprogressives.com###aswift_3_expand newsblaze.com###atf160x600 bustedcoverage.com###atf728x90 ecoustics.com###atf_right_300x250 collegecandy.com###atflb coed.com,collegecandy.com###atfmrec hackthissite.org###atimg webmd.com###attribution_rdr pogo.com###avertising anchorfree.us###b160x600 digitalartsonline.co.uk###b2cPlaceHolder anchorfree.us###b300x250 siliconera.com###b5leaderboard highstakesdb.com###bLeft highstakesdb.com###bRight highstakesdb.com###bSpecificL highstakesdb.com###bSpecificR blinkbox.com###b_ad_zc blinkbox.com###b_ee_de blinkbox.com###b_jd_id huhmagazine.co.uk###back mmoculture.com###background-link wallpapersmania.com###backgroundPopup movie2k.tl,show-links.tv,watchfreemovies.ch###ball soccerbase.com###ball_splash_holder doctor.com###banR intelligencer.ca,siteseer.ca,thepeterboroughexaminer.com,thesudburystar.com###banZone gobackpacking.com###ban_300 neopets.com###ban_bottom england.fm,thestates.fm###banbo virtualnights.com###banderolead ftadviser.com###banlb iloubnan.info###bann goldentalk.com###bann2 absoluteradio.co.uk,adv.li,allmyfaves.com,arsenal.com,blahblahblahscience.com,brandrepublic.com,businessspectator.com.au,christianpost.com,comicsalliance.com,cool-wallpaper.us,cumbrialive.co.uk,dealmac.com,dealsonwheels.co.nz,delcotimes.com,disney.go.com,djmag.co.uk,djmag.com,dosgamesarchive.com,empowernetwork.com,farmtrader.co.nz,guidespot.com,healthcentral.com,icq.com,imgmaster.net,in-cumbria.com,indianexpress.com,insideradio.com,irishcentral.com,keygen-fm.ru,lemondrop.com,lotro-lore.com,mediaite.com,morningjournal.com,movies.yahoo.com,moviesfoundonline.com,mypremium.tv,neave.com,news-herald.com,newstonight.co.za,nhregister.com,northernvirginiamag.com,nzmusicmonth.co.nz,ocia.net,pbs.org,pgpartner.com,popeater.com,poughkeepsiejournal.com,proxy-list.org,ps3-hacks.com,registercitizen.com,roughlydrafted.com,saratogian.com,screenwallpapers.org,securityweek.com,sfx.co.uk,shortlist.com,similarsites.com,soccerway.com,sportinglife.com,stopstream.com,style.com,theoaklandpress.com,thesmokinggun.com,theweek.com,tictacti.com,topsite.com,tortoisehg.bitbucket.org,twistedsifter.com,urlesque.com,vidmax.com,viewdocsonline.com,vps-trading.info,wellsphere.com,wn.com,wsof.com,zootoday.com###banner kiz10.com###banner-728-15 wftlsports.com###banner-Botleft wftlsports.com###banner-Botright drivers.com###banner-bg-scanner imgbox.com,onrpg.com,plasticsnews.com,vladtv.com###banner-bottom worldweb.com###banner-column intouchweekly.com###banner-cross kiz10.com###banner-down-video film.fm###banner-footer mob.org###banner-h400 jacarandafm.com###banner-holder gardentenders.com,homerefurbers.com,sportfishingbc.com###banner-leaderboard kiz10.com###banner-left elle.com,forums.crackberry.com###banner-main cstv.com###banner-promo mp3clan.com###banner-pub kiz10.com,motherboard.tv###banner-right general-fil.es,generalfil.es###banner-search-bottom general-fil.es###banner-search-top torrentpond.com###banner-section irishtimes.com###banner-spacer blocked-website.com,cjonline.com,wftlsports.com###banner-top vladtv.com###banner-top-video mob.org###banner-w790 georgiadogs.com,goarmysports.com,slashdot.org###banner-wrap 4teachers.org,dailyvoice.com,highwayradio.com###banner-wrapper siliconrepublic.com###banner-zone-k businessandleadership.com,siliconrepublic.com###banner-zone-k-dfp globaltimes.cn###banner05 chinatechnews.com,cookinggames.com,emailjokes.co.za,kdoctv.net,killerstartups.com,metroweekly.com,tennisworldusa.org,vk.com###banner1 thegremlin.co.za###banner125 dooyoo.co.uk,kdoctv.net,tennisworldusa.org,vk.com###banner2 pricespy.co.nz###banner250 actiontrip.com,christianpost.com,gamesfree.com,pcmech.com###banner300 977music.com###banner350 securenetsystems.net###bannerB opensourcecms.com###bannerBar ieee.org###bannerBot scientificamerican.com###bannerContain canoe.ca,slacker.com###bannerContainer jumptv.com###bannerContainer_hp_bottom jumptv.com###bannerContainer_hp_top securenetsystems.net###bannerD get.adobe.com###bannerDisplay viz.com###bannerDiv androidzoom.com###bannerDown atomicgamer.com,telefragged.com###bannerFeatures gatewaynews.co.za,ilm.com.pk,ynaija.com###bannerHead showbusinessweekly.com###bannerHeader kumu.com###bannerImageName atdhe.fm,atdhe.so,atdhe.xxx###bannerInCenter securenetsystems.net###bannerL securenetsystems.net###bannerM zam.com###bannerMain pocketgamer.co.uk###bannerRight reuters.com###bannerStrip atomicgamer.com,codecs.com,free-codecs.com,ieee.org,ninemsn.com.au,reference.com###bannerTop sky.com###bannerTopBar search.snap.do###bannerWrapper khl.com###banner_1 yellow.co.nz###banner_120_120 khl.com###banner_2 king-mag.com###banner_468 thelivetvjunction.com###banner_728_base today.az###banner_750x90 yellow.co.nz###banner_760_120 nuffy.net###banner_bg 977music.com,nighttours.com###banner_bottom bubblebox.com,nitrome.com###banner_box mixfmradio.com###banner_center_728 mixfmradio.com###banner_center_728_in tvnz.co.nz###banner_companion epicurious.com,incgamers.com###banner_container nitrome.com###banner_description aol.com###banner_div railwaysafrica.com###banner_footer mynewssplash.com###banner_google fulldls.com###banner_h 3g.co.uk,freshnewgames.com###banner_header mudah.my###banner_holder versus.com###banner_instream_300x250 krzk.com###banner_left bahamaslocal.com###banner_location_sub baltic-course.com###banner_master_top veehd.com###banner_over_vid worldradio.ch###banner_placement_bottom worldradio.ch###banner_placement_right ebuddy.com###banner_rectangle krzk.com###banner_right elyricsworld.com###banner_rr2 nitrome.com###banner_shadow fulldls.com###banner_sq bizrate.com,designboom.com,humorsharing.com,kyivpost.com,linguee.com###banner_top eastonline.eu###banner_up fulldls.com,fulldlsproxy.com###banner_v1 appstorm.net,workawesome.com###banner_wrap washingtonpost.com###banner_wrapper_bottom empiremovies.com,snapfiles.com###bannerbar baltic-course.com,superpages.com###bannerbottom urlcash.net,urlcash.org,whitepages.com.lb,yellowpages.com.jo###bannerbox bdnews24.com###bannerdiv2 fancystreems.com,zonytvcom.info###bannerfloat2 streams.coolsport.tv###bannerfloat22 zawya.com###bannerframezone10325 zawya.com###bannerframezone4 zawya.com###bannerframezone7 tcmagazine.com,tcmagazine.info###bannerfulltext chipchick.com###bannerheader baltic-course.com###bannerleft spellchecker.net###bannerplace freegirlgames.org###bannerplay virusbtn.com###bannerpool driverdb.com,european-rubber-journal.com,mobile-phones-uk.org.uk,offtopic.com,toledofreepress.com###banners bergfiles.com,berglib.com###banners-24 wrmj.com###banners-top eluniversal.com,phuketwan.com###bannersTop krzk.com###banners_bottom insideedition.com###bannerspace-expandable cricketnirvana.com###bannerstrip fitnessmagazine.com###bannertable baltic-course.com,newzglobe.com,webfail.com###bannertop ocregister.com###bannertop2 bhg.com,parents.com###bannerwrapper searchquotes.com###bannerx bernama.com###bannerz h-online.com###bannerzone momversation.com###barker online.barrons.com###barronsUber phonebook.com.pk###basebannercontainer moviecomix.com###bass silverseek.com###bat-region digitalhome.ca###bb egreetings.com###bb-billboard blackbookmag.com###bb-overlay blackbookmag.com###bb-splash egreetings.com###bb-title akihabaranews.com###bbTop nzherald.co.nz###bbWrapper polodomains.com###bbannertop bbc.com###bbccom_bottom[style="width:468px; text-align:right;"] bbc.co.uk,bbc.com###bbccom_leaderboard bbc.co.uk###bbccom_leaderboard_container bbc.co.uk,bbc.com###bbccom_mpu bbc.co.uk###bbccom_sponsor_section bbc.co.uk###bbccom_storyprintsponsorship bustedcoverage.com###bcbtflb bettingsports.com###before_footer mindjolt.com###below-banner mindjolt.com###below-banner-game stopthedrugwar.org###below-masthead rantsports.com###below-post radaronline.com###below_header tgdaily.com###bestcovery_container dailygalaxy.com###beta-inner nigeriafootball.com###bettingCompetition atđhe.net###between_links searchenginejournal.com###bg-atag searchenginejournal.com###bg-takeover-unit livescience.com###bgImage frostytech.com###bg_googlebanner_160x600LH oboom.com###bgfadewnd1 973fm.com.au,buzzintown.com,farmingshow.com,isportconnect.com,mix1011.com.au,mix1065.com.au,newstalkzb.co.nz,ps3news.com,radiosport.co.nz,rlslog.net,runt-of-the-web.com,sharkscope.com###bglink runnerspace.com###bgtakeover forbes.com###bigBannerDiv spacecast.com,treehousetv.com###bigBox chinadaily.com.cn###big_frame canoe.ca,winnipegfreepress.com,worldweb.com###bigbox about.com,cumberlandnews.co.uk,cumbrialive.co.uk,eladvertiser.co.uk,hexhamcourant.co.uk,in-cumbria.com,mg.co.za,newsandstar.co.uk,nwemail.co.uk,timesandstar.co.uk,whitehavennews.co.uk###billboard about.com###billboard2 theblaze.com###billboard_970x250 tech-faq.com,techspot.com###billboard_placeholder joe.ie###billboard_wrapper yp.com.kh###billboards ohio.com###bim-mortgage-container thedailybeast.com###bing-module broadcastingcable.com###biz-main valdostadailytimes.com###biz_marquee slate.com###bizbox_links_bottom play4movie.com###bkg_adv gamesforgirlsclub.com###bl-37 stupidvideos.com###black_sky_header devshed.com,eweek.com###blackscreen backlinkwatch.com,portforward.com###blanket blueletterbible.org###blbSponsors uploadc.com###blinkMe whatculture.com###blinkbox kioskea.net###bloc_middle 1027dabomb.net###block-10 alt1059.com,theticketmiami.com###block-11 alt1059.com###block-22 theticketmiami.com###block-65 uproxx.com###block-728 filmschoolrejects.com###block-banners-top hilarious-pictures.com,winbeta.org###block-block-1 pcdecrapifier.com###block-block-10 newsbusters.org,slideme.org###block-block-11 hilarious-pictures.com,nbr.co.nz###block-block-12 globalgrind.com###block-block-13 gotchamovies.com###block-block-14 abduzeedo.com,driveout.co.za,emaxhealth.com,eturbonews.com,eugeneweekly.com,lasvegascitylife.com,mixtapetorrent.com###block-block-18 dailypaul.com,virus.gr###block-block-19 opposingviews.com###block-block-199 abduzeedo.com###block-block-2 cnsnews.com,prospect.org,webosnation.com###block-block-21 7tutorials.com,carnalnation.com,rslinks.org###block-block-22 7tutorials.com,multiplication.com,thestandard.com,voxy.co.nz###block-block-24 motherjones.com###block-block-27 france24.com###block-block-275 cosmicbooknews.com###block-block-29 motherjones.com###block-block-301 slideme.org###block-block-31 greenbiz.com,latina.com,newsbusters.org###block-block-33 voxy.co.nz###block-block-34 mixtapetorrent.com###block-block-36 dailypaul.com,latina.com###block-block-37 bitchmagazine.org,ovg.tv###block-block-38 latina.com###block-block-39 educationworld.com,greenbiz.com,sonymasterworks.com###block-block-4 latina.com,rslinks.org###block-block-40 eturbonews.com,shape.com###block-block-42 drivesouth.co.nz,motherjones.com###block-block-46 carnalnation.com###block-block-5 abduzeedo.com,freesoftwaremagazine.com###block-block-51 adsoftheworld.com###block-block-52 popsci.com###block-block-53 igbaffiliate.com,nationalenquirer.com###block-block-6 maximumpc.com###block-block-60 maximumpc.com###block-block-61 popsci.com###block-block-63 brownfieldbriefing.com,educationworld.com,minnpost.com,nationalenquirer.com###block-block-7 greenbiz.com###block-block-72 popsci.com###block-block-75 hilarious-pictures.com###block-block-8 tricycle.com###block-block-82 maximumpc.com###block-block-89 maximumpc.com###block-block-96 crooksandliars.com###block-clam-1 crooksandliars.com###block-clam-3 crooksandliars.com###block-clam-7 phonedog.com###block-common-core-voip-business phonedog.com###block-common-core-voip-residential todayonline.com###block-dart-dart-tag-all-pages-header popphoto.com###block-dart-dart-tag-bottom todayonline.com###block-dart-dart-tag-dart-homepage-728x90 popphoto.com###block-dart-dart-tag-top1 medicaldaily.com###block-dfp-bottom ncronline.org###block-dfp-content-1 ncronline.org###block-dfp-content-2 ncronline.org###block-dfp-content-3 ncronline.org###block-dfp-content-4 ncronline.org###block-dfp-home-1 ncronline.org###block-dfp-home-2 ncronline.org###block-dfp-home-3 shape.com###block-dfp-top knowyourmobile.com###block-dialaphone-dialaphone examiner.com###block-ex_dart-ex_dart_adblade_topic 4hi.com.au,4vl.com.au,hotcountry.com.au###block-exponential-exponential-mrec 4hi.com.au,4vl.com.au,hotcountry.com.au###block-exponential-exponential-mrec2 infoworld.com###block-infoworld-sponsored_links 14850.com###block-ofefo-5 14850.com###block-ofefo-7 14850.com###block-ofefo-8 ecnmag.com###block-panels-mini-dart-stamp-ads yourtango.com###block-tango-10 yourtango.com###block-tango-9 ucas.com###block-ucas-ads-header-ad homesandantiques.com###block-views-Promotions-block_1 minnpost.com###block-views-hp_sponsors-block_1 wisebread.com###block-views-nodequeue_14-block asiaone.com###block-views-qoo10-box-block-1 4hi.com.au,4vl.com.au,hotcountry.com.au###block-views-sponsored-links-block wbez.org###block-wbez-blocks-wbez-ad-bottom wbez.org###block-wbez-blocks-wbez-ad-top wpdaddy.com###block1 arsenalnewsreview.co.uk###block_3 moneyearningforum.com###block_html_5 blackhatteam.com###block_html_6 ownedcore.com###block_html_9 tubeplus.me###blocker kveller.com###blogTopWide zdnet.com###blog_spbg scotusblog.com###bloomberg_sponsor kokomoperspective.com###blox-leaderboard-user siouxcityjournal.com###blox-news-alerts-sponsor itreviews.co.uk###bmmBox windowsnetworking.com###bmp-article-script windowsnetworking.com###bmp-side-script kprpam650.com###bnftr-none peliculas-flv.com###bnnr300x250 dnsrsearch.com###bnr reference.com,thesaurus.com###bnrTop ign.com###boards_medrec_relative joox.net###body-sidebar livescore.in###bonus-offers computerworld.com###bonus_resource_center carolinajournal.com###book-abs linuxtopia.org,techotopia.com###bookcover_sky eurogamer.net###boom-box libraryjournal.com###boomBox local.co.uk###borderTab snapfiles.com###borderbar reference.com###bot mp3lyrics.org###bota trutv.com###botleadad phonescoop.com###botlink adf.ly,deezer.com,forums.vr-zone.com,hplusmagazine.com,j.gs,q.gs,u.bb,usniff.com###bottom jillianmichaels.com###bottom-300 dancehallreggae.com,investorplace.com,kiz10.com,lyrics19.com,radionomy.com###bottom-banner vidstatsx.com###bottom-bar news.cnet.com###bottom-leader ohio.com###bottom-leader-position audioreview.com,fayobserver.com,g4chan.com,icanhasinternets.com,legacy.com,thenextweb.com,topcultured.com###bottom-leaderboard startupnation.com###bottom-leaderboard-01 canstar.com.au###bottom-mrec bidnessetc.com###bottom-panel templatemonster.com###bottom-partner-banners techhive.com###bottom-promo thebestdesigns.com###bottom-sponsors timesofisrael.com###bottom-spotlight cartoonnetwork.co.nz,cartoonnetwork.com.au,quotesdaddy.com###bottomBanner rachaelraymag.com###bottomBannerContainer wtmx.com###bottomBanners dailyglow.com###bottomContainer chacha.com###bottomHeaderBannerWrap startribune.com###bottomLeaderboard tnt.tv###bottomLeftBox tnt.tv###bottomMiddleBox teoma.com###bottomPaidList citypaper.com,metrotimes.com,orlandoweekly.com,sacurrent.com###bottomPositions webdesignledger.com###bottomPremiumBanner scientificamerican.com###bottomPromoArea tnt.tv###bottomRightBox search.globososo.com###bottom_adv ifc.com,nerej.com,nyrej.com,phonearena.com,securityweek.com###bottom_banner funkypotato.com###bottom_banner_wrapper toledofreepress.com###bottom_banners avaxsearch.com###bottom_block inquirer.net###bottom_container pressrepublican.com###bottom_leader jamaicaobserver.com###bottom_leaderboard independent.co.uk###bottom_link search.chatzum.com###bottom_links fotolog.com###bottom_pub popoholic.com###bottom_row kingdomfm.co.uk###bottom_section forexnewsnow.com,metropolis.co.jp,tremolo.edgesuite.net###bottombanner ktu.com,z100.com###bottomright2 breaknenter.org,exposay.com###box livescore.in###box-over-content-a oilprice.com###box-premium-articles-sponsor chud.com###box.ad kewlshare.com###box1 kewlshare.com###box3 dillons.com,kroger.com###box3-subPage tnt.tv###box300x250 dmi.ae###boxBanner300x250 yahoo.com###boxLREC planetminecraft.com###box_160btf planetminecraft.com###box_300atf planetminecraft.com###box_300btf planetminecraft.com###box_728atf propertyfinder.ae###box_left_top_300x250 maxim.com###box_takeover_content maxim.com###box_takeover_mask collive.com,ecnmag.com###boxes filesoup.com###boxopus-btn search.yahoo.com###bpla britannica.com###bps-gist-mbox-container brainyquote.com###bq_top_ad turbobit.net###branding-link wandtv.com###brandingfeature believe-or-not.blogspot.com###breadcrumb break.com###breaking-news news-journalonline.com###breaking-sponsor web2.0calc.com###britnexbanner bit-tech.net###broadband-finder-co-uk-120 pcadvisor.co.uk###broadbandchoices_frm wallstcheatsheet.com###broker-box thestreet.com###brokerage psdgraphics.com###bsa-top findicons.com###bsa_leaderboard winrumors.com###bsap_1263017 techsplurge.com###bsats xtragfx.com###bsponsor cineuropa.org###bt indiaresults.com###bt_banner1 kat.ph###bt_bf canoe.ca###btePartena imdb.com###btf_rhs2_wrapper ecoustics.com###btf_right_300x250 coed.com,collegecandy.com###btfmrec collegecandy.com###btfss overdrive.in###btm_banner1 inquirer.net###btmskyscraper profitguide.com###builder-277 torontosun.com###buttonRow muchmusic.com###button[style="position:absolute; top:130px; right:8px;"] alloaadvertiser.com,ardrossanherald.com,barrheadnews.com,bordertelegraph.com,bracknellnews.co.uk,carrickherald.com,centralfifetimes.com,clydebankpost.co.uk,cumnockchronicle.com,dumbartonreporter.co.uk,eastlothiancourier.com,greenocktelegraph.co.uk,helensburghadvertiser.co.uk,irvinetimes.com,largsandmillportnews.com,localberkshire.co.uk,newburyandthatchamchronicle.co.uk,peeblesshirenews.com,readingchronicle.co.uk,sloughobserver.co.uk,strathallantimes.co.uk,the-gazette.co.uk,thevillager.co.uk,troontimes.com,windsorobserver.co.uk###buttons winrumors.com###buttons-125 sloughobserver.co.uk###buttons-mpu-box accuradio.com###buyAlbum news24.com###buybook_box informationweek.com###buylink searchenginejournal.com###buysell buzznet.com###buzz_feedheading news24.com###bw-wrapper businessweek.com###bwMall businessweek.com###bwMall2 businessweek.com###bw_mall help.com###bwp torrentcrazy.com###c2s torrent.cd###c2soffer channel4.com###c4ad-Top counselheal.com,gamenguide.com,latinospost.com,mobilenapps.com,sportsworldreport.com###cTop divinecaroline.com###c_6ad_250h miningmx.com###c_leaderBoard nhl.com###c_mrm3 iafrica.com###c_row1_bannerHolder batman-on-film.com,pettube.com,popoholic.com,yurock.net###ca ciao.co.uk###ca_sponslinks discovermagazine.com###cachee nickutopia.com###cad300 zynga.com###cafe_snapi_zbar bonniegames.com###caja_publicidad popsugar.com###calendar_widget youthincmag.com###campaign-1 care2.com###care2_footer_ads pcworld.idg.com.au###careerone-promo screenafrica.com###carousel sisters-magazine.com###carousel2 france24.com,rfi.fr###caroussel_partenaires abjusa.com,internationalresourcejournal.com###casale answers.com###casale_300x250_3_wrapper answers.com###casale_728x90_2_wrapper answers.com###casale_728x90_wrapper solomontimes.com###casino_banner ninemsn.com.au###cat_hl_171287 finance.ninemsn.com.au###cat_hl_7821719 msn.co.nz###cat_hl_87409 filecore.co.nz,hbwm.com###catfish justinhartman.com###catlinks cryptocoinsnews.com###cb-bg-to bitcoinreviewer.com###cb-section-a > .cb-a-large cryptocoinsnews.com###cb-sidebar-b > #text-85 fresnobee.com###cb-topjobs bnd.com###cb_widget cbc.ca###cbc-bottom-logo xtshare.com###cblocker aviationweek.com,grist.org,linuxinsider.com,neg0.ca###cboxOverlay cbsnews.com###cbsiAd16_100 cbssports.com###cbsiad16_100 cbssports.com###cbsiad18_100 break.com###cdpSliver metrolyrics.com###cee_box metrolyrics.com###cee_overlay xnotifier.tobwithu.com###center > style + h3 + script + script + div > div[style] mp3fusion.net###center2 theatermania.com###centerChannel meettheboss.tv###centerSpacingWrapper checkoutmyink.com###centerbanner reference.com###centerbanner_game rislivetv.com,watchtelevision.eu###centeredcontent rislivetv.com###centeredcontent2 macdailynews.com###cfsnip-widget-93 roomzaar.com###cgp-bb-tag marketingpilgrim.com###channel-sponsors realage.com###channel_sponsor_callout chicagoshopping.com###chshhead_ad espncricinfo.com###ciHomeLeaderboard cineplex.com###cineplex-h-topAds popularmechanics.com###circ popularmechanics.com###circ300x100 popularmechanics.com###circ300x200 popularmechanics.com,seventeen.com###circ300x300 popularmechanics.com###circ620x100 esquire.com###circ_620x200 irishracing.com###classifieds news-gazette.com###clear-footer armorgames.com###click_left_skin armorgames.com###click_right_skin genuineforextrading.com###clickbank pitchero.com###clubSponsor instyle.com###cmfooter inkedmag.com###cmnCompanion saudigazette.com.sa###cmt_spcr cnn.com###cnnLawyersCom concierge.com###cnt_sub_unitdir technabob.com###col1_160 comingsoon.net###col2TopPub mmorpg.com###colFive weather24.com###col_top_fb stv.tv###collapsedBanner aviationweek.com,grist.org,linuxinsider.com,neg0.ca,tv3.co.nz###colorbox search.yahoo.com###cols > #left > #main > ol > li[id^="yui_"] zam.com###column-box:first-child smashingmagazine.com###commentsponsortarget nettleden.com,xfm.co.uk###commercial videobash.com###companion healthguru.com###companionBanner oxygen.com,usanetwork.com###companion_300x250 elleuk.com###component-elle-marketing gotohoroscope.com###con300_250 cpuid.com###console_log share-online.biz###consumer_bottom share-online.biz###consumer_bottom_dl share-online.biz###consumer_top map24.com###cont_m24up memez.com###containTopBox isup.me###container > .domain + p + br + center:last-child isup.me###container > center:last-child > a:first-child isup.me###container > center:last-child > a:last-child videobull.com###container > div > div[style^="position: fixed; "] streamin.to,tvshow7.eu,videobull.com###container > div > div[style^="z-index: "] ebuddy.com###container-banner pons.com###container-superbanner jacksonville.com###containerDeal sedoparking.com###content info.com###content + .P4 4fuckr.com###content > div[align="center"] > b[style="font-size: 15px;"] emillionforum.com###content > div[onclick^="MyAdvertisements"]:first-child autotrader.co.nz,kiz10.com###content-banner lifewithcats.tv###content-bottom-empty-space picocool.com###content-col-3 snow.co.nz###content-footer-wrap prospect.org###content-header-sidebar darkhorizons.com###content-island ifc.com###content-right-b amatuks.co.za###content-sponsors craveonline.com,ego4u.com,washingtonexaminer.com,web.id###content-top lifewithcats.tv###content-top-empty-space sevenload.com###contentAadContainer jellymuffin.com###contentAfter-i vwvortex.com###contentBanner jellymuffin.com###contentBefore-i lifescript.com###content_0_divArticleSponspredContent fileshut.com###content_banner androidpolice.com###content_blob operanews.com###content_bottom_lower theslap.com###content_callout_container gosanangelo.com,kitsapsun.com,knoxnews.com###content_match caller.com,commercialappeal.com,courierpress.com,gosanangelo.com,independentmail.com,kitsapsun.com,knoxnews.com,legacy.com,naplesnews.com,redding.com,reporternews.com,tcpalm.com,timesrecordnews.com,vcstar.com###content_match_wrapper poponthepop.com###content_rectangle madeformums.com,zest.co.uk###contentbanner webreference.com###contentbottomnoinset yorkshireeveningpost.co.uk###contentbox02google yorkshireeveningpost.co.uk###contentbox08 internet.com###contentmarketplace slashdot.org###contextualJobs uexpress.com###continue wikifeet.com###conts > div[style="margin:0px 10px; height:200px; overflow:hidden; position:relative"] ted.com###conversation-sponsor binaries4all.com###convertxtodvd goal.com###cookie_crumb_div sharaget.com###coolDownload sharaget.com###coollist forums.psychcentral.com###copyright pbs.org###corp-sponsor-sec macrumors.com###countdown lef.org###cpSale torrentbit.net###cpa_rotator_block_385_0 peliculasyonkis.com###cpxslidein ratemyprofessors.com###cr-qsb rightdiagnosis.com###cradbotb rightdiagnosis.com,wrongdiagnosis.com###cradlbox1 rightdiagnosis.com,wrongdiagnosis.com###cradlbox2 rightdiagnosis.com,wrongdiagnosis.com###cradrsky2 firsttoknow.com###criteo-container careerbuilder.com###csjstool_bottomleft mustangevolution.com###cta cargames1.com###ctgad thesudburystar.com###ctl00_ContentPlaceHolder1_BigBoxArea2 blogtv.com###ctl00_ContentPlaceHolder1_topBannerDiv spikedhumor.com###ctl00_CraveBanners myfax.com###ctl00_MainSection_BannerCoffee thefiscaltimes.com###ctl00_body_rightrail_4_pnlVideoModule seeklogo.com###ctl00_content_panelDepositPhotos seeklogo.com###ctl00_content_panelDepositPhotos2 leader.co.za###ctl00_cphBody_pnUsefulLinks investopedia.com###ctl00_ctl00_MainContent_A5_ctl00_contentService0 investopedia.com###ctl00_ctl00_MainContent_A5_ctl00_contentService2 leader.co.za###ctl00_ctl00_cphBody_cphColumnBody_cphBannerBodyHeader_userBannerBodyHeader_pnBanners leader.co.za###ctl00_ctl00_cphBody_cphColumnBody_cphColumnMiddleParent_cphNavigationRight_userNavigationRight_userBannerSponsor_pnBanners mouthshut.com###ctl00_ctl00_ctl00_ContentPlaceHolderHeader_ContentPlaceHolderFooter_ContentPlaceHolderBody_zedoParent hurriyetdailynews.com###ctl00_ctl27_ContentPane sufc.co.za###ctl00_ltlSponsors productionhub.com###ctl00_mainPlaceholder_pnlExtraBanner birdchannel.com,smallanimalchannel.com###ctl00_pnlBottomDart community.adlandpro.com###ctl00_slider onetravel.com###ctl07_ctl01_ModuleContent ctmirror.org###ctmirror-sponsors-2 way2sms.com###curtain2 thechive.com###custom-bg-link movies.yahoo.com###customModule daytondailynews.com###cxSubHeader scout.com###da160x600 scout.com###da300x250 cleverbot.com###daArea2 arstechnica.com###daehtsam-da pctipsbox.com###daikos-text-4 heraldnet.com###dailyDealFP cbc.ca###dailydeals fitnessmagazine.com###dailyprize cnbc.com,zone.msn.com###dapIfM1 rawstory.com###darkbackground[style="visibility: visible;"] news.yahoo.com###darla yahoo.com###darla-ad__LREC yahoo.com###darla-ad__LREC2 bestbuy.com###dart-con tesco.com###dartLeftSkipper tesco.com###dartRightSkipper drivewire.com###dart_leaderboard news24.com###datingWidegt pitch.com###datingpitchcomIframe reference.com###dcomSERPTop-300x250 dailydot.com###dd-ad-head-wrapper gazette.com###deal-link charlotteobserver.com,miami.com,momsmiami.com###dealSaverWidget slickdeals.net###dealarea slickdeals.net###dealarea2 11alive.com,9news.com,firstcoastnews.com###dealchicken-todaysdeal timesdispatch.com###dealoftheday blocked-website.com###deals-header news.com.au###deals-module metafilter.com,themorningnews.org###deck instapaper.com###deckpromo girlgames.com###def-box yahoo.com###default-p_24457750 helpwithwindows.com###desc thepiratebay.se###details > #image[target="_blank"] bloggingstocks.com###dfAppPromo thriftyfun.com###dfp-2 madmagazine.com###dfp-300x250 madmagazine.com###dfp-728x90 amherstbulletin.com,concordmonitor.com,gazettenet.com,ledgertranscript.com,recorder.com,vnews.com###dfp_intext_half_page amherstbulletin.com,concordmonitor.com,gazettenet.com,ledgertranscript.com,recorder.com,vnews.com###dfp_intext_med_rectangle cduniverse.com###dgast dailyhoroscope.com###dh-bottomad dailyhoroscope.com###dh-topad vidhog.com###dialog directionsmag.com###dialog-message forums.digitalpoint.com###did_you_know linuxbsdos.com###digocean torrenthound.com###direct.button torrenthound.com,torrenthoundproxy.com###direct2 totalkiss.com###directional-120x600 totalkiss.com###directional-300x250-single datehookup.com###div-Forums_AFT_Top_728x90 articlesnatch.com###div-article-top her.ie,herfamily.ie,joe.co.uk,joe.ie,sportsjoe.ie###div-gpt-top_page gossipcop.com###div-gpt-unit-gc-hp-300x250-atf gossipcop.com###div-gpt-unit-gc-other-300x250-atf geekosystem.com###div-gpt-unit-gs-hp-300x250-atf geekosystem.com###div-gpt-unit-gs-other-300x250-atf modernluxury.com###div-leaderboard-ros chronicleonline.com,sentinelnews.com,theandersonnews.com###div-promo modernluxury.com###div-rectangle-1 modernluxury.com###div-rectangle-2 articlesnatch.com###div-tag-midright articlesnatch.com###div-under-video abbotsfordgasprices.com,albertagasprices.com,barriegasprices.com,bcgasprices.com,calgarygasprices.com,edmontongasprices.com,gasbuddy.com,halifaxgasprices.com,hamiltongasprices.com,kwgasprices.com,londongasprices.com,manitobagasprices.com,montrealgasprices.com,newbrunswickgasprices.com,newfoundlandgasprices.com,novascotiagasprices.com,nwtgasprices.com,ontariogasprices.com,ottawagasprices.com,peigasprices.com,quebeccitygasprices.com,quebecgasprices.com,reginagasprices.com,saskatoongasprices.com,saskgasprices.com,torontogasprices.com,vancouvergasprices.com,victoriagasprices.com,winnipeggasprices.com###div728 klfm967.co.uk###divHeaderBannerRight classiccars.com###divLeaderboard usatoday.com###divMarketplace abbotsfordgasprices.com,albertagasprices.com,barriegasprices.com,bcgasprices.com,calgarygasprices.com,edmontongasprices.com,gasbuddy.com,halifaxgasprices.com,hamiltongasprices.com,kwgasprices.com,londongasprices.com,manitobagasprices.com,montrealgasprices.com,newbrunswickgasprices.com,newfoundlandgasprices.com,novascotiagasprices.com,nwtgasprices.com,ontariogasprices.com,ottawagasprices.com,peigasprices.com,quebeccitygasprices.com,quebecgasprices.com,reginagasprices.com,saskatoongasprices.com,saskgasprices.com,torontogasprices.com,vancouvergasprices.com,victoriagasprices.com,winnipeggasprices.com###divSky abbotsfordgasprices.com,albertagasprices.com,barriegasprices.com,bcgasprices.com,calgarygasprices.com,edmontongasprices.com,gasbuddy.com,halifaxgasprices.com,hamiltongasprices.com,kwgasprices.com,londongasprices.com,manitobagasprices.com,montrealgasprices.com,newbrunswickgasprices.com,newfoundlandgasprices.com,novascotiagasprices.com,nwtgasprices.com,ontariogasprices.com,ottawagasprices.com,peigasprices.com,quebeccitygasprices.com,quebecgasprices.com,reginagasprices.com,saskatoongasprices.com,saskgasprices.com,torontogasprices.com,vancouvergasprices.com,victoriagasprices.com,winnipeggasprices.com###divSkyscraper meettheboss.tv###divSpaceContainerRight sponsorselect.com###divSsnMain crackspider.net###divStayTopLeft gardenstateapartments.com###divTopRight joursouvres.fr,work-day.co.uk,workingdays.ca,workingdays.org,workingdays.us###div_lfsp english.pravda.ru###div_sf_205 english.pravda.ru###div_sf_211 english.pravda.ru###div_sf_214 english.pravda.ru###div_sf_43 english.pravda.ru###div_sf_46 english.pravda.ru###div_sf_47 english.pravda.ru###div_sf_66 english.pravda.ru###div_sf_95 philstar.com###diviframeleaderboard jeuxme.info###divk1 tvonlinegratis.mobi###divpubli vidxden.com###divxshowboxt > a[target="_blank"] > img[width="158"] redown.se###dl afterdawn.com###dlSoftwareDesc300x250 firedrive.com###dl_faster israbox.com###dle-content > .onsearch aol.com###dmn_results coloradocatholicherald.com,hot1045.net,rednationonline.ca###dnn_BannerPane windowsitpro.com###dnn_FooterBoxThree winsupersite.com###dnn_LeftPane cheapoair.com###dnn_RightPane[width="175"] cafonline.com###dnn_footerSponsersPane windowsitpro.com,winsupersite.com###dnn_pentonRoadblock_pnlRoadblock search.yahoo.com###doc #cols #right #east convertmyimage.com###doc2pdf linuxcrunch.com###dock pspmaniaonline.com###dollarade_help msn.co.nz###doubleMrec trulia.com###double_click_backfill freemp3go.com###downHighSpeed solidfiles.com,torrentreactor.com,torrentreactor.net###download-button legendarydevils.com###download1_body movpod.in,vreer.com###downloadbar stuff.co.nz###dpop theoffside.com###dreamteam travelocity.com###drfad-placeholder omg-facts.com,sixbillionsecrets.com###droitetop btstorrent.so###dtl_ erfworld.com###duelannouncement dressupgames.com###dug-header-adv-wrapper dressupgames.com###dug-left-adv-wrapper dressupgames.com###dug-leftcontent-adv-wrapper imgah.com###dwindow torrentroom.com###earn_dir torrentroom.com###earn_spon notdoppler.com###earn_to_die_wrapper torrentroom.com###earn_top search.disconnect.me,search.yahoo.com###east gearslutz.com###ebayFoot gearslutz.com###ebayHead cardomain.com###ebay_listings_wrapper ehow.com###ebooks_container infoworld.com###edit-promo infoworld.com###edit-promo-container nme.com###editorial_sky merriam-webster.com###editors-picks-promo sys-con.com###elementDiv nbr.co.nz###email-signup destructoid.com,japanator.com###emc_header prisonplanet.com###enerfood-banner tcrtroycommunityradio.com###enhancedtextwidget-2 gossipcenter.com###entertainment_skin eweek.com###eoe-sl anilinkz.com###epads1 countryliving.com###epic_banner eplsite.com###epl-banner standard.co.uk###esDating easyvoyage.co.uk###esv-pub-hp theiet.org###et_bannerTop androidpolice.com###execphp-11 androidpolice.com###execphp-15 androidpolice.com###execphp-16 expatica.com###exp-add300x250 azcentral.com,newsarama.com,space.com,stv.tv,usatoday.com,wtsp.com###expandedBanner myfoxatlanta.com,myfoxdc.com###expandedVert directionsmag.com,nationalreview.com###exposeMask boston.com###externalBanner tune.pk###externalPlayer checkoutmyink.com###extralarge_banner yahoo.com###eyebrow > #ypromo zdnet.com###eyebrows stickam.com###f_BottomBanner faxo.com###fa_l esper.vacau.com,nationalreview.com,techorama.comyr.com###facebox esper.vacau.com,filefactory.com###facebox_overlay funnycrazygames.com,playgames2.com,sourceforge.net###fad tucows.com###fad1 askmen.com,dxomark.com###fade softexia.com###faded imagepicsa.com,nashuatelegraph.com###fadeinbox brothersoft.com###fakebodya accountingtoday.com###fancybox-content accountingtoday.com,commentarymagazine.com###fancybox-overlay rapidmore.com###fastdw firstpost.com###fb_mtutor fastcompany.com###fc-ads-imu thedrinknation.com###fcBanner firedrive.com,putlocker.com###fdtb_container firedrive.com###fdvabox dealtime.com,shopping.com###featListingSection globalgrind.com###feature-top yellowpages.ae###feature_company binaryturf.com###feature_gad dubbed-scene.com,exactseek.com,iclarified.com,netfit.co.uk,thepspblog.com,wired.com###featured netbooknews.com###featured-banner nasdaq.com###featured-brokers allakhazam.com,zam.com###featured-promos bbj.hu###featuredBox catchannel.com,dogchannel.com,fishchannel.com,horsechannel.com###featuredProducts teagames.com###featured_h freeworldgroup.com###featuredsponsor comicbookresources.com###features-bigbox talkxbox.com###features-sub youtube.com,youtubeproxy.pk###feed-pyv-container youtube.com###feedmodule-PRO moviecomix.com###filedirect 30for30.espn.com###film-ad komonews.com###fin_askkomo kvi.com###fin_modules_top_above_header news.com.au###find-module-content forexpros.com,investing.com###findABroker imageporter.com###firopage generatorlinkpremium.com###firstleft theverge.com###fishtank siteslike.com###fixedbox[style="margin-top:20px"] booksnreview.com,mobilenapps.com,newseveryday.com,realtytoday.com,scienceworldreport.com,techtimes.com###fixme gwhatchet.com###flan_leader fool.com###flash omgpop.com###flash-banner-top tg4.ie###flash_mpu radiotimes.com###flexible-mpu streamtuner.me###float-bottom altervista.org,bigsports.tv,desistreams.tv,fancystreems.com,freelivesportshd.com,hqfooty.tv,livematchesonline.com,livevss.tv,pogotv.eu,streamer247.com,trgoals.es,tykestv.eu,zonytvcom.info###floatLayer1 cdnbr.biz,zcast.us,zonytvcom.info###floatLayer2 chordfrenzy.com,ganool.com###floating_banner_bottom ganool.com###floating_banner_bottom2 ganool.com###floating_banner_left1 ganool.com###floating_banner_left2 ganool.com###floating_banner_right1 ganool.com###floating_banner_top artima.com###floatingbox company.co.uk###floatingdiv edmunds.com###floodlight zattoo.com###floor[style="display: block;"] people.com###flower-ddrv2 chicagonow.com###flyerboard-wrap popurls.com###fmb thenextweb.com###fmpub_2620 thenextweb.com###fmpub_2620_1 thenextweb.com###fmpub_2621_2 thenextweb.com###fmpub_2621_3 game-debate.com###focus-enclose achieve360points.com###foot socialhype.com,zap2it.com###foot728 boldride.com,chaifm.com,coinurl.com,oocities.org,palipost.com,sicilyintheworld.com,spin.ph,techcentral.co.za,tribejournal.com###footer teesoft.info###footer-800 beso.com,spectator.co.uk###footer-banner tabletmag.com###footer-bar mytalk1071.com###footer-bottom fxstreet.com###footer-brokers economist.com###footer-classifieds forward.com###footer-extras ancientfaces.com,duffelblog.com,geekologie.com###footer-leaderboard gaystarnews.com###footer-links-wrapper3 wetv.com###footer-promo wnd.com###footer-proms popcrush.com###footer-sidebar stuff.co.nz###footer-sitemap mcfc.co.uk###footer-sponsor billboard.com,bloody-disgusting.com,wbez.org###footer-top foxnews.com,mobiletor.com,thescoopng.com###footer-top-wrapper oldcarsweekly.com###footer-widget-area fusible.com,justpushstart.com,ksstradio.com,muthafm.com,swns.com###footer-widgets whatifeelishot.com###footer-wrapper thewhir.com###footer2 livegoals.com###footer4 eventfinda.com,eventfinda.sg,eventfinder.co.nz,eventfinder.com.au,fixya.com,freewebtemplates.com,thebradentontimes.com###footerBanner avfc.co.uk###footerLogos chelseafc.com###footerPartners usatoday.com###footerSponsorOne usatoday.com###footerSponsorTwo chelseafc.com###footerSponsors techworld.com###footerWhitePapers thesouthafrican.com###footer[style="height:200px"] 1019thewave.com,androidcommunity.com,clear99.com,japantoday.com,kat943.com,kcmq.com,kfalthebig900.com,ktgr.com,kwos.com,theeagle939.com,thevillager.com.na,y107.com###footer_banner phpbb.com###footer_banner_leaderboard 1500espn.com,mytalk1071.com###footer_box logopond.com###footer_google royalgazette.com,thehollywoodgossip.com###footer_leaderboard someecards.com###footer_leaderboard_holder sundance.tv###footer_promo androidcommunity.com###footer_wrapper adweek.com###footeraddcontent babyexpert.com,hiphongkong.com,hwhills.com,madcatz.com,madeformums.com,newstatesman.com,visordown.com###footerbanner feedicons.com,phonedog.com###footerboard mytalk1071.com###footerboard_container charlestoncitypaper.com###footerleaderboard macnn.com###footerleft macnn.com###footerright farmonline.com.au###footersponsorbar pbs.org###founding-sponsor themittani.com###fp_leaderboard_1 ytmnd.com###fp_middle amw.com###fpromo250-2 amw.com###fpromo250-3 amw.com###fpromo250-4 amw.com###fpromo78-1 amw.com###fpromo78-2 amw.com###fpromo78-3 foxnews.com###frame2-300x100 5min.com###freeWheelMiddle 5min.com###freeWheelRight topix.com###freecredit virtualmedicalcentre.com###frmsmo-r people.com###fromOurPartners_right babycenter.com###fromOurSponsorsHome theonion.com###from_our_sponsors cnn.com###front-page-mpu thesimsresource.com###frontmc originalfm.com###frontpage_business herold.at###fsb > a > img[width="468"] chicagobusiness.com,footytube.com###ft_leaderboard ieee.org###ftrdwhtpprs teamliquid.net###fuab times247.com###full-banner homehound.com.au###full-leaderboard jewishjournal.com###fullbanner-585 portforward.com###fullpageadvert vidbull.com###fullscreen_exit yasni.ca,yasni.co.uk,yasni.com###fullsizeBannerContainer yasni.ca,yasni.co.uk,yasni.com###fullsizeWrapper penny-arcade.com###funding-h vladtv.com###fw_promo tinypic.com###fxw_ads interscope.com###g300x250 claro-search.com,isearch.babylon.com,search.babylon.com###gRsTopLinks hoobly.com###ga1 trulia.com###gac_rs 9bis.net,elyrics.net,oldversion.com###gad speedyshare.com###gad1 speedyshare.com###gad2 cnet.com###gafscsa-middle telegraph.co.uk###gafsslot1 telegraph.co.uk###gafsslot2 bustedcoverage.com,collegecandy.com###galad300 hot995.com###gallery_adbg teagames.com###gameinfobanner armorgames.com###gameleaderboard kongregate.com###gamespotlight agame.com###gameunderbanner thegazette.com###gaz_article_bottom_featured_jobs mobiles24.com###gbar illawarramercury.com.au###gbl_adcolumn geekwire.com###geekwork buznews.com###gemSponsored cioupdate.com,datamation.com,earthweb.com,linuxplanet.com,serverwatch.com###gemhover yahoo.com###genie-widgetgroup theonion.com###geobanner desimartini.com###getPosition mininova.org###getstarted ktar.com###gfp vh1.com###gft-network:last-child mtv.com###gft-sponsors vancouversun.com###giftguidewidget phillytrib.com###gkBannerTop ngrguardiannews.com###gkBannerTopAll concrete.tv###gkBanners howdesign.com,moviecritic.com.au,orble.com,realitytvobsession.com###glinks theguardian.com###global-jobs people.com###globalrecirc infoplease.com###gob colonhealth.net###gooBox0 mozillazine.org###goobot gearlive.com,noscript.net,stv.tv###google mu.nu###google-banner t3.com###google-container-4 news.stv.tv###google-endarticle salon.com###google-single photojpl.com###google01 about.com###google1 about.com###google2 inquirer.net###googleFooter yfrog.com###google_ads_div_yfrog2_landing_ad_container softnyx.net###google_banner winnipegfreepress.com###google_box m-w.com,merriam-webster.com###google_creative_1 m-w.com,merriam-webster.com###google_creative_3 testfreaks.co.uk###google_links windows2universe.org###google_mockup indianexpress.com###google_new indianexpress.com###google_new_top screenindia.com###google_pic psdeluxe.com###google_top tips.net###googlebig forums.studentdoctor.net###googlefloat sapostalcodes.za.net###googlehoriz variety.com###googlesearch magtheweekly.com###googleskysraper mozillazine.org###gootop truckinginfo.com###got-questions asylum.co.uk###goviralD sourceforge.jp###gpt-sf_dev_300 neopets.com###gr-ctp-premium-featured bbccanada.com###gradientbox proboards.com###gravity-stories-1 darkreading.com###greyPromoArea tv3.co.nz###greyout binaries4all.com###gright eq2flames.com###grightcolumn > .sidewid pep.ph###group_2 bamkapow.com###gs300x250 jobs.aol.com###gsl aol.com###gsl-bottom torlock.com,torrentfunk.com,yourbittorrent.com###gslideout gtaforums.com###gtaf_ad_forums_bottomLeaderboard gtaforums.com###gtaf_ad_forums_topLeaderboard gtaforums.com###gtaf_ad_forums_wideSkyscraper gtaforums.com###gtaf_ad_index_topLeaderboard gtaforums.com###gtaf_ad_index_wideSkyscraper gtaforums.com###gtaf_ad_topics_bottomLeaderboard gtaforums.com###gtaf_ad_topics_topLeaderboard hotonlinenews.com###guessbanner justinhartman.com###gumax-article-picture hinduwebsite.com###gupad disney.go.com###gutter playlist.com###gutter-skyscraper logotv.com###gutterLeft logotv.com###gutterRight moneycontrol.com###gutter_id1 moneycontrol.com###gutter_id2 kzupload.com###gw_overlay totalcmd.pl###h1r health365.com.au###h365-sponsors stickam.com###h_TopBanner techweb.com###h_banner nickutopia.com###had300 theglobeandmail.com###halfpager-art-1 downloadhelper.net###halloween-pb comedy.com###hat heatworld.com###hbar webhostingtalk.com###hc-postbit-1 webhostingtalk.com###hc-postbit-3 healthcentral.com###hcs_ad0 megashare.com###hd-link prevention.com###hdr-top weatherbug.com###hdr-top-wrap flashgot.net###head a[target="_blаnk"] virtualnights.com###head-banner androidheadlines.com,molempire.com###head-banner728 geekologie.com###head-leaderboard avfc.co.uk###headAcorns countytimes.co.uk###headBanner quotes-love.net###head_banner fxempire.com###head_banners webdesignstuff.com###headbanner adsoftheworld.com,anglocelt.ie,animalnetwork.com,cartoonnetworkhq.com,eeeuser.com,engineeringnews.co.za,eveningtimes.co.uk,floridaindependent.com,hellmode.com,heraldscotland.com,incredibox.com,information-management.com,krapps.com,link-base.org,meathchronicle.ie,mothering.com,nevadaappeal.com,offalyindependent.ie,petapixel.com,theroanoketribune.org,tusfiles.net,unrealitymag.com,vaildaily.com,washingtonindependent.com,westmeathindependent.ie,yourforum.ie###header filehippo.com###header-above-content-leaderboard theblemish.com###header-b fanrealm.net,flix.gr,fonearena.com,frontlinesoffreedom.com,girlgames.com,pa-magazine.com,progressivenation.us,scmp.com,snow.co.nz,snowtv.co.nz,spectator.co.uk,stickgames.com,sunnewsonline.com###header-banner gearculture.com###header-banner-728 dominicantoday.com###header-banners diyfashion.com###header-blocks ideone.com###header-bottom allakhazam.com###header-box:last-child bestvpnserver.com,themiddlemarket.com###header-content davidwalsh.name###header-fx ancientfaces.com,g4chan.com,myrecordjournal.com,news-journalonline.com,phillymag.com,telegraph.co.uk,usatoday.com###header-leaderboard menshealth.com###header-left-top-region amctv.com,ifc.com,motorhomefacts.com,sundance.tv,wetv.com###header-promo veteranstoday.com###header-right-banner2 eweek.com###header-section-four vanityfair.com###header-subs sys-con.com###header-title honolulumagazine.com,yourtango.com###header-top bocanewsnow.com###header-widgets nisnews.nl###header-wrap moreintelligentlife.com,sci-news.com###header0 kaldata.net###header2 inventorspot.com###header2-section nickutopia.com###header728 gizbot.com###headerAdd projectorcentral.com###headerBanner yummy.ph###headerLeaderBoard darkreading.com###headerPromo rivieraradio.mc###headerPromoArea talksport.net###headerPromoContainer fresnobee.com###headerSectionLevel atpworldtour.com###headerSponsor coloradosprings.com###headerSponsorImage coloradosprings.com###headerSponsorText chelseafc.com###headerSponsors eonline.com###headerSpot beliefnet.com###headerTopExtra agriaffaires.ca,agriaffaires.co.uk,agriaffaires.us###header_ban countytimes.com,elleuk.com,energyfm.net,heritage.com,slots4u.com,squidoo.com###header_banner thetechjournal.com###header_bottom worddictionary.co.uk###header_inpage sedoparking.com###header_language pcworld.idg.com.au,petapixel.com,washingtoncitypaper.com###header_leaderboard edie.net###header_mainNav5b digitalpoint.com###header_middle washingtoncitypaper.com###header_pencilbar cointelegraph.com###header_promo fastcompany.com###header_region johnbridge.com###header_right_cell zug.com###header_rotate popsci.com,popsci.com.au###header_row1 pedulum.com,washingtonexaminer.com,yourtango.com###header_top bitenova.nl,bitenova.org###header_un chocablog.com,commenthaven.com,hwhills.com,movieentertainment.ca,nikktech.com,smallscreenscoop.com,thisisnotporn.net###headerbanner hongkiat.com###headerbanner01 nationalgeographic.com,scienceblogs.com###headerboard i-comers.com###headerfix technotification.com###headlineatas allakhazam.com###hearthhead-mini-feature grist.org###hellobar-pusher kansascity.com###hi-find-n-save hi5.com###hi5-common-header-banner atdhe.fm,atdhe.so,atdhe.xxx###hiddenBannerCanvas wbond.net###hide_sup flashi.tv###hideall rapidvideo.org,rapidvideo.tv###hidiv rapidvideo.org###hidiva rapidvideo.org###hidivazz itweb.co.za###highlight-on codinghorror.com###hireme quill.com###hl_1_728x90 carzone.ie###hm-MPU hidemyass.com###hmamainheader japanprobe.com###hmt-widget-additional-unit-4 cstv.com,gobulldogs.com,gohuskies.com,theacc.com,ukathletics.com,usctrojans.com,villanova.com###holder-banner und.com###holder-banner-top cstv.com,navysports.com,texassports.com###holder-skyscraper cstv.com,goairforcefalcons.com,goarmysports.com,gopack.com,goterriers.com,texassports.com,umassathletics.com,villanova.com###holder-story radiobroadcaster.org,thedailyrecord.com###home-banner yellowpages.com.lb###home-banner-box motherjones.com###home-billboard dailydomainer.com###home-insert-1 homeportfolio.com###home-rec abcya.com###home-skyscraper gaana.com###home-top-add homeportfolio.com###home-tower maxim.com###homeModuleRight politics.co.uk###homeMpu techradar.com###homeOmioDealsWrapper thebradentontimes.com###homeTopBanner radiocaroline.co.uk###home_banner_div khmertimeskh.com###home_bottom_banner creativeapplications.net###home_noticias_highlight_sidebar gpforums.co.nz###home_right_island inquirer.net###home_sidebar facebook.com###home_sponsor_nile facebook.com###home_stream > .uiUnifiedStory[data-ft*="\"ei\":\""] khmertimeskh.com###home_top_banner gumtree.co.za###home_topbanner spyka.net###homepage-125 edmunds.com###homepage-billboard youtube.com###homepage-chrome-side-promo 10tv.com###homepage-leader studentbeans.com###homepage_banner beepbeep.com,rr.com###homepagewallpaper pcmech.com###homepromo fashiontv.com###horiz_banner sydneyolympicfc.com###horiz_image_rotation horsetalk.co.nz###horseclicks webmd.com###hot-tpcs jamaica-gleaner.com###hotSpotLeft jamaica-gleaner.com###hotSpotRight newsminer.com###hot_deals_banner politiken.dk###hotels_banner phnompenhpost.com###hoteltravel cioupdate.com###houseRibbonContainer mp4upload.com###hover rottentomatoes.com###hover-bubble itproportal.com###hp-accordion active.com###hp-map-ad worldweatheronline.com###hp_300x600 eweek.com###hp_hot_stories collegecandy.com###hplbatf bhg.com###hpoffers bustedcoverage.com###hpss lhj.com###hptoprollover staradvertiser.com###hsa_bottom_leaderboard careerbuilder.com###htcRight[style="padding-left:18px; width: 160px;"] hdcast.org###html3 pregen.net###html_javascript_adder-3 maxkeiser.com###html_widget-11 maxkeiser.com###html_widget-2 maxkeiser.com###html_widget-3 dailystar.co.uk###hugebanner chocablog.com###i1 i-programmer.info###iProgrammerAmazoncolum finweb.com###ib_inject iconfinder.com###icondetails-banner airfrance.co.uk###id_banner_zone cnn.com###ie_column sciencemag.org###iframe_box more.com###iframe_for_div_c_6ad_banner yavideo.tv###iframebanner unitconversion.org###ileft thepiratebay.se###image > img:last-child zigzag.co.za###imageLeft zigzag.co.za###imageRight movshare.net###imagecontmvshre macthemes2.net###imagelinks epdrama.com###imageurl sharksrugby.co.za###imgTitleSponsor new-magazine.co.uk,soshiok.com,star-magazine.co.uk###imu stjobs.sg###imu-big stjobs.sg###imu-small2 cio.com###imu_box newcarnet.co.uk###imuad theyeshivaworld.com###inArticle computerworlduk.com###inArticleRelatedArticles computerworlduk.com###inArticleSiteLinks audioz.eu###inSidebar > #src_ref rawstory.com###in_article_slot_1 rawstory.com###in_article_slot_2 soccer24.co.zw###in_house_banner youtubeproxy.pk###include2 telegraph.co.uk###indeed_widget_wrapper egotastic.com###index-insert independent.co.uk###indyDating share-links.biz###inf_outer news.com.au###info-bar share-links.biz###infoC technologytell.com###infobox_medium_rectangle_widget technologytell.com###infobox_medium_rectangle_widget_features technologytell.com###infobox_techmedia mg.co.za###inline_banner thaindian.com###inlineblock startpage.com###inlinetable eurweb.com###inner div[id^="div-gpt-ad-"] krnb.com,myk104.com###inner-footer newsdaily.com###insert pep.ph###insideBanner yakima-herald.com###instoryadhp maxim.com###intHorizBanner maxim.com###intSkirt electronicproducts.com###interVeil newsbusters.org###interad shmoop.com###intermediary gizmodo.co.uk###interruptor campustechnology.com###intersitial campustechnology.com,fcw.com,mcpmag.com,rcpmag.com,reddevnews.com,redmondmag.com,visualstudiomagazine.com###intersitialMask adage.com###interstitial boldsky.com###interstitialBackground maxim.com###interstitialCirc boldsky.com,gizbot.com###interstitialRightText gizbot.com###interstitialTitle giantlife.com,newsone.com###ione-jobs_v2-2 elev8.com,newsone.com###ione-jobs_v2-3 giantlife.com###ione-jobs_v2-4 about.com###ip0 idolforums.com###ipbwrapper > .borderwrap > .ipbtable:nth-child(7):nth-last-child(3n+2) ip-adress.com###ipinfo[style="padding-left:10px;vertical-align:top;width:380px"] investorplace.com###ipm_bottom_sidebar_ad-3 investorplace.com###ipm_featured_partners-5 investorplace.com###ipm_sidebar_ad-3 metrolyrics.com###ipod unitconversion.org###iright ironmanmag.com.au###iro_banner_leaderboard inquirer.net###is-sky-wrap imageshack.us###is_landing drivearcade.com,freegamesinc.com###isk180 gameplanet.com.au###island1 gameplanet.com.au###island2 computerworld.com###itjobs_module mercurynews.com###jBar_dailyDeals businessmirror.com.ph,joomlarulez.com###ja-banner itwire.com###ja-header sigsiu.net###ja-rightcol chicagodefender.com###ja-topbar messianictimes.com###ja-topmenu messianictimes.com###ja-topsl2 pandora.tv###japan_ad careerbuilder.com###jdpSponsoredBy jimdo.com###jimdobox kansascity.com###jobStart_widget theregister.co.uk###jobs-promo earthweb.com###jomfooter nowtoronto.com###jrBanners twitch.tv###js-esl300 episodeninja.com,pspmaniaonline.com###jveajheuayuevatta episodeninja.com,pspmaniaonline.com###jveavnnennneanealk rentals.com###ka_300x250_1 rentals.com###ka_468x60_1 rentals.com###ka_728x90_1 thenationonlineng.net###kaizenberg zonadictoz.com.ar###kaizer sport24.co.za###kalahari bigislandnow.com###kbig_holder way2sms.com###kidloo nationalgeographic.com###kids_tophat_row1 waoanime.tv###kittenoverlay wkrg.com###krg_oas_rail topix.com###krillion_block topix.com###krillion_container herold.at###kronehit comicgenesis.com###ks_da kewlshare.com###ksupdates teamfortress.tv###ku-bottom solarmovie.com###l_35061 123people.co.uk###l_banner thedugoutdoctors.com,thehoopdoctors.com###l_sidebar gantdaily.com###l_sidebar_banners watchdocumentary.com###lad themtn.tv###landing_55 maltatoday.com.mt,maltatoday.info###landscape_banner law.com###lawJobs tsviewer.com###layer 1tvlive.in###layer2 juicefm.com,pulse1.co.uk,pulse2.co.uk,signal1.co.uk,signal2.co.uk,swanseasound.co.uk,theregister.co.uk,thewave.co.uk,wave965.com,wirefm.com,wishfm.net###lb audiofanzine.com###lbContainerBlock networkworld.com###lb_container networkworld.com###lb_container_top inquirer.net###lb_ear inquirer.net###lb_ear2 redferret.net###lb_wrap bustedcoverage.com###lbbtf play.tm###lbc lankabusinessonline.com###lbo-ad-leadboard mofunzone.com###ldrbrd_td gpsreview.net###lead armedforcesjournal.com###leadWrap imperfectparent.com###leada tripit.com###leadboard gamesindustry.biz,investopedia.com,iphonic.tv,kontraband.com,motherproof.com,nutritioncuisine.com,sansabanews.com,thestreet.com,topgear.com,venturebeat.com,vg247.com###leader duffelblog.com###leader-large bakersfieldnow.com,katu.com,keprtv.com,komonews.com,kpic.com,kval.com,star1015.com###leader-sponsor agriland.ie,ballitonews.co.za,blackburnnews.com,bloody-disgusting.com,football-talk.co.uk,foxnews.com,irishpost.co.uk,longislandpress.com,mobiletoday.co.uk,mobiletor.com,morningledger.com,pcgamerhub.com,soccersouls.com,thescoopng.com,thewrap.com,urbanmecca.net,youngzimbabwe.com###leader-wrapper heraldstandard.com###leaderArea xe.com###leaderB firstnationsvoice.com,hbr.org,menshealth.com,pistonheads.com###leaderBoard wellness.com###leaderBoardContentArea totalfilm.com###leaderContainer girlsgogames.com###leaderData computerworlduk.com###leaderPlaceholder zdnet.com###leaderTop behealthydaily.com###leader_board pandora.com###leader_board_container icanhascheezburger.com,memebase.com,thedailywh.at###leader_container tvguide.com###leader_plus_top tvguide.com###leader_top about.com,animeseason.com,ariacharts.com.au,ask.fm,boomerangtv.co.uk,businessandleadership.com,capitalxtra.com,cc.com,charlotteobserver.com,classicfm.com,crackmixtapes.com,cubeecraft.com,cultofmac.com,cyberciti.biz,datpiff.com,economist.com,educationworld.com,electronista.com,espn980.com,eurogamer.net,extremetech.com,food24.com,football.co.uk,gardensillustrated.com,gazette.com,greatgirlsgames.com,gtainside.com,hiphopearly.com,historyextra.com,houselogic.com,ibtimes.co.in,ibtimes.co.uk,iclarified.com,icreatemagazine.com,instyle.co.uk,jaxdailyrecord.com,jillianmichaels.com,king-mag.com,ksl.com,lasplash.com,lrb.co.uk,macnn.com,nfib.com,onthesnow.ca,onthesnow.co.nz,onthesnow.co.uk,onthesnow.com,onthesnow.com.au,penny-arcade.com,pets4homes.co.uk,publishersweekly.com,realliving.com.ph,realmoney.thestreet.com,revolvermag.com,rollcall.com,salary.com,sciencedirect.com,sciencefocus.com,smoothradio.com,spin.ph,talonmarks.com,thatgrapejuice.net,thehollywoodgossip.com,theserverside.com,toofab.com,topcultured.com,uncut.co.uk,wheels24.co.za,whitepages.ae,windsorstar.com,winsupersite.com,wired.com,xfm.co.uk###leaderboard chicagomag.com###leaderboard-1-outer boweryboogie.com,safm.com.au###leaderboard-2 usnews.com###leaderboard-a 1029thebuzz.com,925freshradio.ca###leaderboard-area usnews.com###leaderboard-b atlanticcityinsiders.com,autoexpress.co.uk,bigissue.com,galvestondailynews.com,pressofatlanticcity.com,theweek.co.uk###leaderboard-bottom scientificamerican.com###leaderboard-contain daniweb.com,family.ca,nationalparkstraveler.com,sltrib.com,thescore.com###leaderboard-container netmagazine.com###leaderboard-content wvmetronews.com###leaderboard-footer news-gazette.com###leaderboard-full-size canadianbusiness.com,macleans.ca,moneysense.ca,todaysparent.com###leaderboard-header idahostatejournal.com,lonepeaklookout.com###leaderboard-middle belgrade-news.com###leaderboard-middle-container treehousetv.com###leaderboard-play kfoxtv.com,kirotv.com,ktvu.com,kxly.com,wfmz.com,wftv.com,whiotv.com,wjactv.com,wpxi.com,wsbtv.com,wsoctv.com,wtov9.com###leaderboard-sticky carbuyer.co.uk,cnet.co.uk,galvestondailynews.com,oaoa.com,pressofatlanticcity.com,themonitor.com###leaderboard-top wvmetronews.com###leaderboard-wrap geekologie.com,pcgamer.com,pep.ph,stuttgartcitizen.com###leaderboard-wrapper drdobbs.com,todaystmj4.com,uexpress.com###leaderboard1 computerweekly.com,drdobbs.com,inquirer.net,uexpress.com###leaderboard2 uexpress.com###leaderboard3 futuremark.com,tarot.com###leaderboardArea stardoll.com###leaderboardContainer roadfly.com###leaderboardHead law.com###leaderboardMidPage iconosquare.com###leaderboardNL tarot.com###leaderboardOuter computerweekly.com###leaderboardPlacement brandsoftheworld.com###leaderboardTop businesstimes.com.sg###leaderboardWrapper teleread.com###leaderboard_1 thestandard.com###leaderboard_banner joe.ie###leaderboard_bottom gtainside.com,marieclaire.co.uk,marketingmag.ca###leaderboard_container rte.ie###leaderboard_footer inquirer.net###leaderboard_frame inc.com###leaderboard_label managerzone.com###leaderboard_landing englishbaby.com###leaderboard_outer metroland.net###leaderboard_space investorwords.com###leaderboard_wrap okcupid.com,thehollywoodgossip.com###leaderboard_wrapper movie-analyzer.com###leaderboardbanner jewishjournal.com###leaderboardgray jewishjournal.com###leaderboardgray-825 hollywoodinterrupted.com,westcapenews.com###leaderboardspace thaindian.com###leadrb fastpic.ru###leads bleedingcool.com###leaf-366 bleedingcool.com###leaf-386 eel.surf7.net.my###left search.yahoo.com###left > #main > div[id^="yui_"] search.yahoo.com###left > #main > div[id^="yui_"][class] > ul[class] > li[class] search.yahoo.com###left > #main > div[id^="yui_"][class]:first-child > div[class]:last-child noscript.net###left-side > div > :nth-child(n+3) a[href^="/"] technologyexpert.blogspot.com###left-sidebarbottom-wrap1 shortlist.com###left-sideburn sysresccd.org###left1 cokeandpopcorn.com###left4 cokeandpopcorn.com###left5 sparknotes.com###leftAd telegramcommunications.com###leftBanner gizgag.com###leftBanner1 nowinstock.net###leftBannerBar infobetting.com###leftBannerDiv watchcartoononline.com###leftBannerOut leo.org###leftColumn > #adv-google:first-child + script + .gray leo.org###leftColumn > #adv-leftcol + .gray thelakewoodscoop.com###leftFloat yahoo.com###leftGutter newsok.com###leftRailContent sosuanews.com###left_banner island.lk###left_banner_adds1 nitrome.com###left_bottom_bg nitrome.com###left_bottom_box nitrome.com###left_bottom_shadow notdoppler.com###left_link whitepages.co.nz###left_skyscraper nitrome.com###left_skyscraper_container theblaze.com###left_top_160x600 foodingredientsfirst.com###leftbar-banner urlcash.net###leftbox sarugbymag.co.za###leftclick stuff.co.nz###leftgutter hotonlinenews.com###leftmenu 810varsity.com###leftsidebanner americanlivewire.com###lefttower tvsquad.com###legal supercars.net###lemonFree msn.com###lgad linuxinsider.com,technewsworld.com###lightview tubeplus.me###like_panel racinguk.com,webpagetest.org###links fox6now.com###links-we-like feedyes.com###links54005 the-news.net###linkssection fileinfo.com###linkunits imagebunk.com###linkxbox mappy.com###liquid-misc etaiwannews.com,taiwannews.com.tw###list_google2_newsblock etaiwannews.com,taiwannews.com.tw###list_google_newsblock ikascore.com###listed 951shinefm.com###listen-now-sponsor nymag.com###listings-sponsored sawlive.tv###llvvd webmd.com###lnch-promo sunshinecoastdaily.com.au###localOffers whereis.com###location_advertisement mapcrunch.com###locinfo cryptocoinsnews.com###logo + .cb-large meteo-allerta.it,meteocentrale.ch,meteozentral.lu,severe-weather-centre.co.uk,severe-weather-ireland.com,vader-alarm.se###logo-sponsor cnettv.cnet.com###logoBox runnow.eu,sunderlandvibe.com###logos arenafootball.com###logos-wrap usnews.com###loomia_display herold.at###loveat eurogamer.net###low-leaderboard byutvsports.com###lower-poster proudfm.com###lower_leaderboard hinduwebsite.com###lowergad mefeedia.com###lowright300 africam.com###lr_comp_default_300x150 africam.com,cnn.com,epdaily.tv,hernandotoday.com,highlandstoday.com,kob.com,tbo.com,techsupportforum.com,tivocommunity.com,wbng.com###lr_comp_default_300x250 music.yahoo.com###lrec fox.com###lrec-wrapper yahoo.com###lrec2 music.yahoo.com###lrecTop yahoo.com###lrec_mod inquirer.net###ls-bb-wrap inquirer.net###ls-right iphonelol.org###lsmspnad celebstyle.com###lucky linuxinsider.com,technewsworld.com###lv_overlay drugs.com###m1a miller-mccune.com###magSubscribe wired.com###magazine_rightRail_A videos.rawstory.com###magnify_widget_playlist_item_shop_container rawstory.com###magnify_widget_playlist_item_shop_content mediaite.com###magnify_widget_rect_content mediaite.com###magnify_widget_rect_handle reallygoodemails.com###mailchimp-link adv.li###main search.yahoo.com###main .dd .layoutCenter .compDlink search.yahoo.com###main .dd .layoutCenter > .compDlink search.yahoo.com###main .dd[style="cursor: pointer;"] > .layoutMiddle cryptocoinsnews.com###main > .mobile > .special > center search.yahoo.com###main > .reg > li[id^="yui_"][data-bid] > [data-bid] search.yahoo.com###main > div[id^="yui_"] > ul > .res search.yahoo.com###main > div[id^="yui_"].rVfes:first-child search.yahoo.com###main > div[id^="yui_"].rVfes:first-child + #web + div[id^="yui_"].rVfes search.yahoo.com###main > div[id^="yui_"][class][data-bk][data-bns]:first-child search.yahoo.com###main > div[style="background-color: rgb(250, 250, 255);"] search.yahoo.com###main > noscript + div[id^="yui_"][class][data-bk][data-bns="Yahoo"] search.yahoo.com###main > noscript + div[id^="yui_"][class][data-bk][data-bns="Yahoo"] + #web + div[id^="yui_"][class][data-bk][data-bns="Yahoo"] search.yahoo.com###main > ol li[id^="yui_"] search.yahoo.com###main > style:first-child + * + #web + style + * > ol[class]:first-child:last-child search.yahoo.com###main > style:first-child + * > ol[class]:first-child:last-child mobilesyrup.com###main-banner yasni.ca,yasni.co.uk,yasni.com###main-content-ac1 stylist.co.uk###main-header sfbay.ca###main-market monhyip.net###mainBaner nme.com###mainBanner leo.org###mainContent > #rightColumn:last-child w3schools.com###mainLeaderboard necn.com###main_117 necn.com###main_121 necn.com###main_175 net-security.org###main_banner_topright bitenova.org###main_un pureoverclock.com###mainbanner search.aol.com###maincontent + script + div[class] > style + script + h3[class] holidayscentral.com###mainleaderboard kansas.com,kansascity.com,miamiherald.com,sacbee.com,star-telegram.com###mainstage-dealsaver bazoocam.org###mapub reuters.com###marchex macdrifter.com###marked-widget eatingwell.com###marketFeaturedSponsors itworld.com###market_place iii.co.uk###marketdatabox_content_footer xmlgold.eu###marketimg myspace.com###marketing nbcconnecticut.com,nbcphiladelphia.com,nbcwashington.com###marketingPromo techworld.com###marketingSlots cio.co.uk###marketingSlotsContainer style.com###marketing_mod crispygamer.com###marketingbox arnnet.com.au,cio.com.au,computerworld.com.au,foodandwine.com,healthcareitnews.com,msn.com,nbcnews.com,techworld.com.au,travelandleisure.com,tvnz.co.nz,yahoo.com###marketplace goodgearguide.com.au,pcworld.idg.com.au,techworld.com.au###marketplace-padding usatoday.com###marketplace2 inquirer.net###marketplace_vertical_container inquirer.net###marketplacebtns columbian.com###marketplaces-widget-new vidhog.com###mask bellinghamherald.com,bnd.com###mastBanner pcadvisor.co.uk###mastHeadTopLeft pricegrabber.com###mast_logo_advertisement creditinfocenter.com,examiner.com###masthead arstechnica.com###masthead + #pushdown-wrap pbs.org###masthead1 pbs.org###masthead2 yahoo.com###mbAds internet.com###mbEnd maps.google.com###mclip google.com.au###mclip_control sandiego6.com###mealsandsteals thehothits.com###med-rec myspace.com###medRec yourdailymedia.com###medRectATF citypaper.com,metrotimes.com###medRectangle active.com###med_rec_bottom active.com###med_rec_top lancasteronline.com###med_rect ostatic.com###media_partner_gallery finance.yahoo.com###mediabankrate_container megom.tv###mediaspace_wrapper + script + #timeNumer surk.tv###mediasrojas1 xxlmag.com###medium-rec pastemagazine.com,weebls-stuff.com###medium-rectangle cgchannel.com###mediumRectangle newburyportnews.com###mediumRectangle_atf pons.com,pons.eu###medium_rec kexp.org###medium_rectangle pandora.com###medium_rectangle_container pricegrabber.com###mediumbricks king-mag.com###mediumrec ebaumsworld.com###mediumrect smashingmagazine.com###mediumrectangletarget americanidol.com,mindjolt.com,xxlmag.com###medrec hackaday.com,joystiq.com,peninsuladailynews.com###medrect atom.com,happytreefriends.com###medrect-container joystiq.com###medrectrb michiguide.com###medrectright techrepublic.com,zdnet.com###medusa nashuatelegraph.com###meerkat-wrap concrete.tv###megabanner encyclopedia-titanica.org###menuheaderbio spinitron.com###merchpanel ginbig.com,rushlane.com###message_box theweedblog.com###meteor-slides-widget-3 fulldls.com###meth_smldiv imageporter.com###mezoktva dannychoo.com###mg-blanket-banner thetechjournal.com,torrents.de,torrentz.ch,torrentz.com,torrentz.eu,torrentz.in,torrentz.li,torrentz.me,torrentz.ph,torrentz.unblockt.com###mgid everyjoe.com###mgid-widget menshealth.com###mh_top_promo_special liligo.com###midbanner soccerphile.com###midbanners dvdactive.com###middleBothColumnsBanner wpxi.com,wsbtv.com###middleLeaderBoard theimproper.com###middle_banner_widget proudfm.com###middle_leaderboard trutv.com,workswithu.com###middlebanner workswithu.com###middlebanner300x100 thevarguy.com###middlebannerwrapper mefeedia.com###midright300 stuff.co.nz###mightyape-mobwidget pricegrabber.com###minibricks pch.com###minipath_panel devshed.com###mixedspons msn.com###mlad mercurynews.com###mn_SP_Links dllme.com###mobile-insert bit-tech.net###mobile-phones-co-uk-120 pcpro.co.uk###mobile_app_developers longreads.com###mobile_banner iphoneapplicationlist.com###mobiscope-banner nytimes.com###mod-ln-ctr-bt nytimes.com###mod-ln-ctr-top philly.com###mod-storytext ciao.co.uk###mod_ph_merchoffer mail.yahoo.com###modal-upsell tradingmarkets.com###modalbg moneymakerdiscussion.com###module25 desiretoinspire.net###moduleContent18450223 goodhousekeeping.com###moduleEcomm elle.com,womansday.com###moduleMightLike menshealth.co.uk###module_promotion huffingtonpost.co.uk###modulous_right_rail_edit_promo huffingtonpost.co.uk###modulous_sponsorship_2 wikia.com###monaco_footer cnn.com###moneySponsorBox cnn.com###moneySponsors itworld.com###more_resources topix.com###mortgages_block gold1043.com.au,kiis1065.com.au,mix1011.com.au,wsfm.com.au###mos-headerRow1 newssun.com###mosFeatureHome newssun.com###mosHeaderTop insideradio.com###mosSkyscraper tooorgle.com###most_popular anonymouse.org###mouselayer way2sms.com###movbox watchfreemovies.ch###movie take40.com###mpIsland bounty.com,carpages.co.uk,clubwebsite.co.uk,cumberlandnews.co.uk,djmag.co.uk,djmag.com,donedeal.ie,eladvertiser.co.uk,f1fanatic.co.uk,gumtree.com,hexhamcourant.co.uk,icreatemagazine.com,in-cumbria.com,itv.com,lbc.co.uk,lonelyplanet.com,metalhammer.co.uk,nettleden.com,newsandstar.co.uk,nickjr.co.uk,nme.com,nwemail.co.uk,play.tm,politics.co.uk,radiotimes.com,sportinglife.com,studentbeans.com,taletela.com,thatgrapejuice.net,thecourier.co.uk,thefootballnetwork.net,timesandstar.co.uk,topgear.com,tv.com,uncut.co.uk,webdesignermag.co.uk,whitehavennews.co.uk,zoopla.co.uk###mpu t3.com###mpu-container-2 stv.tv###mpu-content2 topgear.com###mpu3 heatworld.com###mpuLikeSection chow.com###mpu_1 oliveoiltimes.com###mpu_banner1 instyle.co.uk###mpu_div avforums.com###mpu_inpost iconosquare.com###mpusCenter fox.com,momversation.com,spin.ph,thexfactorusa.com###mrec nwherald.com###mrec-atf nwherald.com###mrec-btf fox.com###mrec-wrapper spin.ph###mrec3 ninemsn.com.au###mrecMod pcworld.co.nz###mrec_bottom nzherald.co.nz###mrktImg katu.com,kval.com###mrktplace_tabbed computerweekly.com###msAD_cw_adtech_leaderboard_2 computerweekly.com###msAD_cw_adtech_skyscraper_two_4 search.cnbc.com###ms_aur yourwire.net###mscount sharetera.com###msgDiv ninemsn.com.au,ninemsn.seek.com.au###msnhd_div3 yourmovies.com.au,yourrestaurants.com.au,yourtv.com.au###msnmd_div everybody.co.nz###msnnz_ad_medium_rectangle magicseaweed.com###msw-js-toggle-leader knowfree.net,thepspblog.com###mta_bar heritage.com###mthotdeal mtv.co.uk###mtv-shop ratemyprofessors.com###mtvBlock nitrome.com###mu_2_container malwarehelp.org###multimedia_box myspace.com###music_googlelinks myspace.com###music_medrec wikinvest.com###mw-header yahoo.com###mw-ysm-cm news.yahoo.com###mw-ysm-cm_2-container miningweekly.com###mw_q-search-powered yahoo.com###my-promo-hover rally24.com###myBtn tcpdump.com###myID bloggersentral.com###mybsa lolzparade.com###mylikes_bar_all_items jobstreet.com.sg###mysitelogo forums.creativecow.net###mz[width="100%"][valign="top"][style="padding:20px 30px 30px 30px;"] + td[width="150"][valign="top"][style="padding:6px 10px 0px 0px;"]:last-child rentalcars.com###name_price_ad irishracing.com###naobox entrepreneur.com###nav-promo-link browserleaks.com###nav-right-logo amazon.com###nav-swmslot rentals.com###nav_credit_report kuhf.org###nav_sponsors hongfire.com###navbar_notice_9 usnews.com###navbuglink esl.eu###navi_partner webinspector.se###navigation_left nbc.com###nbc-300 truelocal.com.au###ndmadkit-memrec-1 netcraft.com###netcraft-links-bottom moviefone.com###netflix-promo sandiegozoo.org###newhomesponosrs askmen.com###news_popup soccerlens.com###newsnowlogo yakima-herald.com###newspaperads theroot.com###nextbox africam.com###nikona aww.com.au###ninemsn-footer-container cosmopolitan.com.au,dolly.com.au###ninemsn-leaderboard-footer theberry.com###ninth-box motherjones.com###node-body-break website-unavailable.com###norecords news.yahoo.com###north sensis.com.au###northPfp mail.yahoo.com###northbanner sankakucomplex.com###noscript-warning forums.somethingawful.com###notregistered pv-tech.org###noty_bottomRight_layout_container majorgeeks.com###novb air1.com,klove.com###nowPlayingBuyMusic firststreaming.com###nowplayinglinks financialpost.com,nationalpost.com###npLeaderboard about.com,gamefaqs.com###nrelate_related_placeholder backpage.com###nsaLeaderBoard nascar.com###nscrRCol160ad nascar.com###nscrVideoAd totalcmd.pl###nucom mail.yahoo.com###nwPane thedailybeast.com###nwsub_container centralillinoisproud.com###nxcms_dotbiz nydailynews.com###nydn-ads nydailynews.com###nydn-footer-ad nydailynews.com###nydn-top-ad nytimes.com###nytmm-ss-big-ad-1 nytimes.com###nytmm-ss-big-ad-2 btmon.com###oafa_target_4 btmon.com###oafa_target_6 masala.com###oas-300x600 autotrader.co.uk###oas-banner-0 autotrader.co.uk###oas-banner-1 autotrader.co.uk###oas-banner-2 autotrader.co.uk###oas-banner-3 masala.com###oas-mpu-left\<\/div\> masala.com###oas-mpu-right\<\/div\> moneycontrol.com###oas_bottom foreclosure.com###obFlyMain cbslocal.com###ob_paid_header cleantechnica.com###obog_signup_widget cincinnati.com###ody-asset-breakout democratandchronicle.com###ody-dealchicken popsugar.com###offer-widget funnyplace.org###oglas-desni cnet.com###omTrialPayImpression ikeahackers.net###omc-sidebar .responsive-image cleantechnica.com,watch-anime.net###omc-top-banner wbaltv.com,wesh.com,wmur.com###omega omg.yahoo.com###omg-lrec azcentral.com###on-deals eweek.com###oneAssetIFrame yeeeah.com###orangebox 24wrestling.com###other-news totallycrap.com###oursponsors allyou.com,cbsnews.com,chron.com,coastalliving.com,cookinglight.com,denverpost.com,ew.com,jpost.com,myrecipes.com,mysanantonio.com,nydailynews.com,pcmag.com,seattlepi.com,seattletimes.com,sfgate.com,southernliving.com,standard.co.uk,sunset.com,telegraph.co.uk,theguardian.com,travelandleisure.com,washingtonexaminer.com,ynetnews.com###outbrain_widget_0 foxnews.com,jpost.com,london24.com,nydailynews.com###outbrain_widget_1 cbslocal.com,chron.com,mysanantonio.com,seattlepi.com,sfgate.com,standard.co.uk###outbrain_widget_2 bbc.com,cnbc.com,jpost.com,si.com###outbrain_widget_3 si.com###outbrain_widget_5 hiphopwired.com###outbrain_wrapper familysecuritymatters.org###outer_header engadget.com###outerslice mp4upload.com###over beststreams.ru###over-small playhd.eu###over_player_msg2 deviantart.com###overhead-you-know-what agame.com,animestigma.com,bestream.tv,newsbtc.com,notdoppler.com,powvideo.net,uploadcrazy.net,vidcrazy.net,videoboxone.com,videovalley.net,vidup.org,vipboxeu.co,vipleague.me,viponlinesports.eu,webmfile.tv###overlay bidnessetc.com###overlay10 speedvid.net,thevideo.me###overlayA euro-pic.eu,imagewaste.com###overlayBg theyeshivaworld.com###overlayDiv bestreams.net,happystreams.net,played.to,realvid.net###overlayPPU reference.com###overlayRightA thelakewoodscoop.com###overlaySecondDiv deditv.com,fleon.me,mypremium.tv,skylo.me,streamme.cc,tooshocking.com,xtshare.com###overlayVid agame.com###overlay_bg canoe.ca###overlay_bigbox viplivebox.eu###overlay_content viplivebox.eu###overlay_countdown thedailybeast.com###overlay_newsweek_container reference.com###overlayleftA rocksound.tv###overtake imfdb.org###p-Sponsors lyricwiki.org###p-navigation + .portlet scout.com###p2rightbar espnf1.com###p320B espnf1.com###p320T coloradoan.com,thenewsstar.com###p360_left_wrapper superfundo.org,tv3.co.nz###pa yahoo.com###paas-lrec yahoo.com###paas-mrec interfacelift.com###page > .row[style="height: 288px;"] abbreviations.com,definitions.net,quotes.net,synonyms.net###page-bottom-banner huffingtonpost.com###page-header animenewsnetwork.com,animenewsnetwork.com.au###page-header-banner whathifi.com###pageHeader nbcmontana.com###pageHeaderRow1 weather.com###pageSpon2 ninemsn.com.au###page_content_right radaronline.com###page_content_right_small facebook.com###pagelet_ads_when_no_friend_list_suggestion warriorforum.com###pagenav_menu + div[align="center"] > a[target="_blank"] > img offtopic.com###pagenav_menu + table[height="61"][cellspacing="0"][cellpadding="0"][border="0"][width="100%"] sme.sk###paidLinks thesun.co.uk###paidProducts weather.com###paid_search zonelyrics.net###panelRng creativenerds.co.uk###panelTwoSponsors nymag.com###partner-feeds orange.co.uk###partner-links businessinsider.com.au###partner-offers hwbot.org###partner-tiles kat.ph###partner1_button nbcphiladelphia.com,nbcsandiego.com,nbcwashington.com###partnerBar hbr.org###partnerCenter nickjr.com###partnerLinks newser.com###partnerTopBorder huffingtonpost.com###partner_box euronews.com###partner_link weather.com###partner_offers delish.com###partner_promo_module_container whitepages.ca,whitepages.com###partner_searches itworld.com###partner_strip ew.com###partnerbar ew.com###partnerbar-bottom collegecandy.com###partnerlinks cioupdate.com,datamation.com,earthweb.com,fastseduction.com,mfc.co.uk,muthafm.com,ninemsn.com.au,porttechnology.org,threatpost.com,wackyarchives.com###partners arcticstartup.com###partners_125 behealthydaily.com###partners_content ganool.com###pateni patheos.com###patheos-ad-region boards.adultswim.com###pattern-area way2sms.com###payTM300 carscoops.com###payload binaries4all.com###payserver binaries4all.com###payserver2 pbs.org###pbsdoubleclick nydailynews.com###pc-richards demap.info###pcad tucows.com###pct_popup_link retrevo.com###pcw_bottom_inner retrevo.com###pcw_int retrevo.com###pcw_showcase realestate.yahoo.com###pdp-ysm torrentreactor.net###peelback vosizneias.com###perm theonion.com###personals avclub.com###personals_content topix.com###personals_promo portforward.com###pfconfigspot pricegrabber.com,tomshardware.com###pgad_Top pricegrabber.com###pgad_topcat_bottom richkent.com###phone video2mp3.net###phone_top knowyourmobile.com###phones4u300_body knowyourmobile.com###phones4u_body knowyourmobile.com###phones4u_masthead knowyourmobile.com###phones4u_masthead_500 everyjoe.com###php-code-1 toonzone.net###php_widget-18 triggerbrothers.com.au###phpb2 triggerbrothers.com.au###phpsky dnsleak.com,emailipleak.com,ipv6leak.com###piaad picarto.tv###picartospecialadult heatworld.com###picks fool.com###pitch ratemyprofessors.com###placeholder728 autotrader.co.uk###placeholderTopLeaderboard sockshare.com###playdiv div[style^="width:300px;height:250px"] sockshare.com###playdiv tr > td[valign="middle"][align="center"]:first-child allmyvideos.net,vidspot.net###player_img magnovideo.com###player_overlay catstream.pw,espnwatch.tv,filotv.pw,orbitztv.co.uk###playerflash + script + div[class] ytmnd.com###please_dont_block_me cargames1.com###plyadu mma-core.com###plyr > #overlay sheridanmedia.com###poll-sponsor vg.no###poolMenu backlinkwatch.com###popUpDiv videolinkz.us###popout hybridlava.com###popular-posts newsbtc.com,team.tl###popup dxomark.com###popupBlock newpct.com###popupDiv journal-news.net###popwin cosmopolitan.com###pos_ams_cosmopolitan_bot nvideo.eu###posa ganool.com###post-35426 io9.com,jalopnik.com,jezebel.com,kotaku.com,lifehacker.com###postTransitionOverlay quickmeme.com###post[style="display: block;min-height: 290px; padding:0px;"] wired.com###post_nav techcrunch.com###post_unit_medrec multichannel.com###postscript-top-wrapper addictinggames.com###potw bnet.com###powerPromo edrinks.net,mortgageguide101.com,twirlit.com###ppc zdnet.com###pplayLinks prisonplanet.com###ppradio cnsnews.com###pre-content pinknews.co.uk###pre-head chronicleonline.com,cryptoarticles.com,roanoke.com,sentinelnews.com,theandersonnews.com###pre-header foodnetworkasia.com,foodnetworktv.com###pre-header-banner surfline.com###preRoll thevideo.me,vidup.me###pre_counter dragcave.net###prefooter bizjournals.com###prefpart yourmovies.com.au,yourrestaurants.com.au,yourtv.com.au###preheader-ninemsn-container mixupload.org###prekla bassmaster.com###premier-sponsors-widget nzgamer.com###premierholder netnewscheck.com,tvnewscheck.com###premium-classifieds youtube.com###premium-yva nextag.com###premiumMerchant usatoday.com###prerollOverlayPlayer 1cookinggames.com###previewthumbnailx250 news24.com###pricechecklist gamekyo.com###priceminister queenscourier.com###primary-sidebar inquirer.net###primaryBottomSidebar snapfiles.com###prodmsg snapfiles.com###prodmsgdl gizmodo.com.au###product-finder productwiki.com###product-right masstimes.org,thecatholicdirectory.com###products androidauthority.com###products_widget rapid8.com###prom notepad.cc,runnow.eu###promo nextgengamingblog.com###promo-300x250 nextgengamingblog.com###promo-468x60 artistsandillustrators.co.uk###promo-area computerandvideogames.com###promo-h miniclip.com###promo-mast wayfm.com###promo-roll miniclip.com###promo-unit nbcuni.com###promo1 nbcuni.com###promo9 fhm.com###promoContainer 8newsnow.com###promoHeader kat.ph###promoLeechmonster asseenontv.com###promoMod macupdate.com###promoSidebar maxim.com###promoSlide wsj.com###promo_container yahoo.com###promo_links_list phonescoop.com###promob agame.com###promobar mdjonline.com,thestranger.com###promos und.com###promos-story-wrap und.com###promos-wrap networkworld.com###promoslot eclipse.org,hotscripts.com###promotion reminderfox.mozdev.org###promotion3 sherdog.net###promotion_container newsroomamerica.com###promotional thebulls.co.za###promotions thesuperficial.com###pronto-container thehomepage.com.au###prop-foot-728x90 independent.co.uk,standard.co.uk###propCar my-proxy.com###proxy-bottom newyorker.com###ps2_fs2_yrail newyorker.com###ps3_fs1_yrail ecommercetimes.com,linuxinsider.com,macnewsworld.com,technewsworld.com###ptl sk-gaming.com###pts sk-gaming.com###ptsf rocvideo.tv###pu-pomy digitalversus.com###pub-banner digitalversus.com###pub-right-top cnet.com###pubUpgradeUnit jeuxvideo-flash.com###pub_header frequence-radio.com###pub_listing_top skyrock.com###pub_up tvlizer.com###pubfooter hellomagazine.com###publi marca.com###publi_sup surinenglish.com###publicidades_top thenextweb.com###pubtop herold.at###puls4 newsweek.com###pulse360 nymag.com,thebusinessdesk.com###pushdown pep.ph###pushdown-wrapper neopets.com###pushdown_banner miningweekly.com###q-search-powered thriveforums.org###qr_defaultcontainer.qrcontainer inbox.com,search.aol.com###r search.yahoo.com###r-e search.yahoo.com###r-n search.yahoo.com###r-s dnssearch.rr.com,optu.search-help.net###rSrch oldgames.sk###r_TopBar ultimate-guitar.com###r_a thedugoutdoctors.com,thehoopdoctors.com###r_sidebar gantdaily.com###r_sidebar_banners mobilenapps.com###r_sponsor barbavid.com###rabbax technozeast.com,youtube-mp3.org###rad answers.com###radLinks ehow.co.uk###radlinks freevermontradio.org###rads collegefashion.net###rainbowsparkleunicorn armorgames.com###randomgame amazon.com###raw-search-desktop-advertising-tower-1 imageporter.com###ray_ban reference.com###rc pt-news.org###rcb1 holytaco.com###re_ad_300x250 yahoo.com###rec akihabaranews.com###recHome akihabaranews.com###recSidebar deliciousdays.com###recipeshelf wambie.com###recomendar_728 tucows.com###recommended_hdg doodle.com###rect pixdaus.com###rectBanner ap.org,moviemistakes.com,tvfanatic.com,zattoo.com###rectangle bizrate.com###rectangular dict.cc###rectcompactbot dict.cc###recthome dict.cc###recthomebot 1tiny.net###redirectBlock bloemfonteincelticfc.co.za###reebok_banner expertreviews.co.uk###reevoo-top-three-offers pcadvisor.co.uk###reevooComparePricesContainerId pcadvisor.co.uk###reevooFromPrice bnet.com###reg-overlay yahoo.com###reg-promos dailyxtra.com###region-superleaderboard thedailystar.net###rehab_ad_tds_web xpgamesaves.com###reklam atdhe.eu###reklama_mezi_linky filmschoolrejects.com###related-items moneynews.com,newsmax.com,newsmaxhealth.com,newsmaxworld.com###relatedlinks winkeyfinder.com###render thehomepage.com.au###res-mid-728x90 thehomepage.com.au###res-side-160x600 thehomepage.com.au###res-top-728x90 mumsnet.com###reskin_left mumsnet.com###reskin_right zillow.com###resource-center zdnet.com###resourceCentre computerworld.com,networkworld.com###resources-sponsored-links url.org###resspons1 url.org###resspons2 herold.at###resultList > #downloadBox search.iminent.com,start.iminent.com###result_zone_bottom search.iminent.com,start.iminent.com###result_zone_top filesdeck.com###results-for > .r > .rL > a[target="_blank"][href^="/out.php"] search.excite.co.uk###results11_container indeed.com###resultsCol > .lastRow + div[class] indeed.com###resultsCol > .messageContainer + style + div + script + style + div[class] qwant.com###resultsShoppingList nowtorrents.com###results_show_2 cnet.com###reviewsPanel msn.co.nz###rhc_find ninemsn.com.au###rhc_mrec imdb.com###rhs-sl imdb.com###rhs_cornerstone_wrapper pcworld.idg.com.au###rhs_resource_promo stream2watch.com###rhw_footer eel.surf7.net.my,macdailynews.com,ocia.net###right search.yahoo.com###right .dd .mb-11 + .compList search.yahoo.com###right .dd > .layoutMiddle search.yahoo.com###right .dd[style="cursor: pointer;"] > .layoutMiddle search.yahoo.com###right .dd[style^="background-color:#FFF;border-color:#FFF;padding:"] .compList search.yahoo.com###right .first > div[style="background-color:#fafaff;border-color:#FAFAFF;padding:4px 10px 12px;"] search.yahoo.com###right .reg > li[id^="yui_"][data-bid] > [data-bid] search.yahoo.com###right .res ninemsn.com.au###right > .bdr > #ysm search.yahoo.com###right > .searchRightMiddle + div[id]:last-child search.yahoo.com###right > .searchRightTop + div[id]:last-child ~images.search.yahoo.com,search.yahoo.com###right > div > .searchRightMiddle + div[id]:last-child ~images.search.yahoo.com,search.yahoo.com###right > div > .searchRightTop + [id]:last-child ~images.search.yahoo.com,search.yahoo.com###right > div:first-child:last-child > [id]:first-child:last-child search.yahoo.com###right > div[id] > div[class] > div[class] > h2[class]:first-child + ul[class]:last-child > li[class] search.yahoo.com###right > span > div[id] > div[class] div[class] > span > ul[class]:last-child > li[class] search.yahoo.com###right [class][data-bk][data-bns] search.yahoo.com###right div[style="background-color:#fafaff;border-color:#FAFAFF;padding:4px 10px 12px;"] search.yahoo.com###right li[id^="yui_"] .dd > .layoutMiddle search.yahoo.com###right ol li[id^="yui_"] > .dd > .layoutMiddle 123chase.com###right-adv-one foodingredientsfirst.com,nutritionhorizon.com,tgdaily.com###right-banner vidstatsx.com###right-bottom treatmentabroad.net###right-inner wenn.com###right-panel-galleries shortlist.com###right-sideburn narutofan.com###right-spon vidstatsx.com###right-top realcleartechnology.com###right-wide-skyscraper popsci.com###right1-position gtopala.com###right160 popsci.com###right2-position tnt.tv###right300x250 cartoonnetwork.co.nz,cartoonnetwork.com.au,cartoonnetworkasia.com,cdcovers.cc,gizgag.com,prevention.com,slacker.com,telegramcommunications.com###rightBanner watchcartoononline.com###rightBannerOut cantyouseeimbusy.com###rightBottom linuxforums.org,quackit.com###rightColumn maltatoday.com.mt###rightContainer thelakewoodscoop.com###rightFloat yahoo.com###rightGutter cosmopolitan.com###rightRailAMS befunky.com###rightReklam totalfark.com###rightSideRightMenubar playstationlifestyle.net###rightSkyscraper itworldcanada.com###rightTopSponsor files.fm###right_add sosuanews.com###right_banner mediacorp.sg###right_banner_placeholder ffiles.com###right_col necn.com###right_generic_117 necn.com###right_generic_121 necn.com###right_generic_175 themtn.tv###right_generic_47 necn.com###right_generic_v11_3 notdoppler.com###right_link psinsider.e-mpire.com###right_main_1 hardware.info###right_top theblaze.com###right_top_160x600 mumbaimirror.com###rightarea vg247.com###rightbar > #halfpage urlcash.net###rightbox sarugbymag.co.za###rightclick portable64.com###rightcol liveleak.com###rightcol > .sidebox > .gradient > p > a[target="_blank"] cokeandpopcorn.com###rightcol3 mysuncoast.com###rightcolumnpromo stuff.co.nz###rightgutter 810varsity.com###rightsidebanner herold.at###rightsponsor elyricsworld.com###ringtone tubeconverter.net###ringtone-button youtump3.com###ringtoner egotastic.com,idolator.com,socialitelife.com,thesuperficial.com###river-container megarapid.net,megashare.com,scrapetorrent.com###rmiad megashare.com###rmishim brenz.net###rndBanner actiontrip.com,comingsoon.net,craveonline.com,dvdfile.com,ecnmag.com,gamerevolution.com,manchesterconfidential.co.uk,thefashionspot.com,videogamer.com###roadblock windowsitpro.com,winsupersite.com###roadblockbackground winsupersite.com###roadblockcontainer mirror.co.uk###roffers-top barclaysatpworldtourfinals.com###rolex-small-clock kewlshare.com###rollAdRKLA moviezer.com###rootDiv[style^="width:300px;"] lionsrugby.co.za###rotator lionsrugby.co.za###rotator2 powerboat-world.com###rotator_url alliednews.com,americustimesrecorder.com,andovertownsman.com,athensreview.com,batesvilleheraldtribune.com,bdtonline.com,chickashanews.com,claremoreprogress.com,cleburnetimesreview.com,clintonherald.com,commercejournal.com,commercial-news.com,coopercrier.com,cordeledispatch.com,corsicanadailysun.com,crossville-chronicle.com,cullmantimes.com,dailyiowegian.com,dailyitem.com,daltondailycitizen.com,derrynews.com,duncanbanner.com,eagletribune.com,edmondsun.com,effinghamdailynews.com,enewscourier.com,enidnews.com,farmtalknewspaper.com,fayettetribune.com,flyergroup.com,gainesvilleregister.com,gloucestertimes.com,goshennews.com,greensburgdailynews.com,heraldbanner.com,heraldbulletin.com,hgazette.com,homemagonline.com,itemonline.com,jacksonvilleprogress.com,joplinglobe.com,journal-times.com,journalexpress.net,kokomotribune.com,lockportjournal.com,mankatofreepress.com,mcalesternews.com,mccrearyrecord.com,mcleansborotimesleader.com,meadvilletribune.com,meridianstar.com,mineralwellsindex.com,montgomery-herald.com,mooreamerican.com,moultrieobserver.com,muskogeephoenix.com,ncnewsonline.com,newburyportnews.com,newsaegis.com,newsandtribune.com,niagara-gazette.com,njeffersonnews.com,normantranscript.com,orangeleader.com,oskaloosa.com,ottumwacourier.com,palestineherald.com,panews.com,paulsvalleydailydemocrat.com,pellachronicle.com,pharostribune.com,pressrepublican.com,pryordailytimes.com,randolphguide.com,record-eagle.com,register-herald.com,register-news.com,reporter.net,rockwallheraldbanner.com,roysecityheraldbanner.com,rushvillerepublican.com,salemnews.com,sentinel-echo.com,sharonherald.com,shelbyvilledailyunion.com,starbeacon.com,stwnewspress.com,suwanneedemocrat.com,tahlequahdailypress.com,theadanews.com,thedailystar.com,thelandonline.com,themoreheadnews.com,thesnaponline.com,tiftongazette.com,times-news.com,timesenterprise.com,timessentinel.com,timeswv.com,tonawanda-news.com,tribdem.com,tribstar.com,unionrecorder.com,valdostadailytimes.com,washtimesherald.com,waurikademocrat.com,wcoutlook.com,weatherforddemocrat.com,woodwardnews.net###rounded-corners-findnsave zam.com###row-top 3news.co.nz###row1_fixed_SideF cybergamer.com###row_banner_dvrtsmnt yttalk.com###rpmtop parentdish.co.uk###rr-amazon search-results.com###rr_sa_container redsharknews.com###rsBannerStrip core77.com###rsDesignDir theprovince.com,vancouversun.com###rsm_widget_wrapper eprop.co.za###rt-top rte.ie###rte-header-leaderboard rte.ie###rte-masthead-topleft pages.ebay.com###rtm_1658 ebay.ie###rtm_NB motors.ebay.com###rtm_div_193 ebay.co.uk,ebay.com###rtm_html_194 ebay.ie###rtm_html_225 ebay.co.uk###rtm_html_274 ebay.co.uk###rtm_html_275 ebay.co.uk,ebay.com###rtm_html_391 ebay.com###rtm_html_441 ebay.co.uk###rtm_html_566 ebay.co.uk###rtm_html_567 ebay.co.uk,ebay.com###rtm_html_569 food.com###rz-leaderboard-wrap crawler.com###s classifieds.co.uk###s123results crawler.com###s2 capitalradiomalawi.com###s5_pos_below_body_1 capitalradiomalawi.com###s5_pos_bottom_row2_1 capitalradiomalawi.com###s5_pos_top_row1_1 search.charter.net,search.frontier.com###sRhtSde youtube-mp3.org###sad nickutopia.com###sad336 presidiacreative.com###sads salary.com###sal_pg_abv msn.com###sales1 msn.com###sales2 msn.com###sales3 msn.com###sales4 watchwweonline.org###samdav-locker watchwweonline.org###samdav-wrapper wbez.org###sb-container nickutopia.com###sb160 codefuture.co.uk###sb_left hwhills.com###sb_left_tower scholastic.com###schlSkyscraper sciencesdaily.info###sciencedaily_rectangle cartoonnetwork.com###scraper alloy.com###screen_scene_module newsbusters.org###screenoverlay pcweenies.com###scribol techpounce.com###scribol-block flexiblewebdesign.com###scroll opensubtitles.org###scrubbuad_style espnscrum.com###scrumRhsBgMpu espnscrum.com###scrumRhsBgTxtLks hentai2read.com###sct_banner_980_60 stardoll.com###sdads_bt_2 zillow.com###search-featured-partners docspot.com###search-leaderboard youtube.com###search-pva zoozle.org###search_right zoozle.org###search_topline bitenova.nl,bitenova.org###search_un tribune.com.ng###searchmod-surround search.yahoo.com###sec-col urlgone.com###secondColumn kontraband.com###second_nav_container kontraband.com###second_nav_content_container zuula.com###secondary smarterfox.com###secondary-banner way2sms.com###secreg2 neoseeker.com###section-pagetop desiretoinspire.net###sectionContent2275769 desiretoinspire.net###sectionContent5389870 whatismyipaddress.com###section_right edomaining.com###sedo-search scoop.co.nz###seek_table searchenginejournal.com###sej-bg-takeover-left searchenginejournal.com###sej-bg-takeover-right inc.com###select_services isohunt.to###serps .title-row > a[rel="nofollow"][href="#"] website-unavailable.com###servfail-records gamesgames.com###sgAdMrCp300x250 girlsgogames.com###sgAdMrScp300x250 gamesgames.com###sgAdScCp160x600 girlsgogames.com###sgAdScHp160x600 girlsgogames.com###sgAdScScp160x600 in.msn.com###shaadicom msn.com###shadi_flash mercola.com###shadowbox_container tubeplus.me###share localhostr.com###share2 youtube.com###shelf-pyv-container shidurlive.com###shidurdiv someecards.com###shop expertreviews.co.uk###shopperButton broadcastnewsroom.com###shopperartbox macworld.com###shopping cnet.com.au###shopping-339279174 indianexpress.com###shopping_deals qj.net###shoppingapi bellasugar.com,tressugar.com###shopstyle-sidebar-container 10minutemail.com###shoutouts ytv.com###show-big-box businessweek.com###showInterstitial tunegenie.com###showad isxdead.com###showbox coolhunting.com###showcase famouscelebritiespictures.com,xtremevbtalk.com###showimage crunchyroll.ca###showmedia_square_adbox_new tribune.com.ng###showmodules fbcoverlover.com###shownOnlyOnceADay wwtdd.com###showpping si.com###si-com-ad-widget usatoday.com###side-banner1 usatoday.com###side-banner2 feedmyapp.com###side-bsa thebestdesigns.com###side-sponsor gamingunion.net###side-sponsors howtogeek.com###side78 iphonefaq.org###sideBarsMiddle iphonefaq.org###sideBarsTop iphonefaq.org###sideBarsTop-sub tomsguide.com,tomshardware.co.uk###sideOffers khmertimeskh.com,webappers.com###side_banner beatweek.com,filedropper.com,mininova.org,need4file.com,rockdizfile.com,satelliteguys.us###sidebar cryptoarticles.com###sidebar > #sidebarBlocks sharktankblog.com###sidebar > #text-85 yauba.com###sidebar > .block_result:first-child nuttynewstoday.com###sidebar > div[style="height:120px;"] ha.ckers.org###sidebar > ul > li:first-child + li + div[align="center"] krebsonsecurity.com###sidebar-250 pa-magazine.com###sidebar-banner tvlizer.com###sidebar-bottom lionsdenu.com,travelwkly.com###sidebar-bottom-left lionsdenu.com###sidebar-bottom-right krebsonsecurity.com###sidebar-box sbs.com.au###sidebar-first cloudpro.co.uk###sidebar-first-inner eaglewavesradio.com.au###sidebar-header tricycle.com###sidebar-logos equestriadaily.com###sidebar-right-search domaininvesting.com,elliotsblog.com###sidebar-sps allshowsdaily.com###sidebar-wrapper > div > div[style^="z-index: "] deviantart.com###sidebar-you-know-what bored.com###sidebar1head p2pnet.net###sidebar2 hybridlava.com###sidebar200 uncoached.com,unrealitymag.com###sidebar300X250 petapixel.com,pgatour.com###sidebar300x250 thecourier.co.uk###sidebarMiddleCol inquirer.net###sidebarTabs inquirer.net###sidebarTabs1 inquirer.net###sidebarTabs2 thetechjournal.com###sidebar_after_1000px sundancechannel.com###sidebar_banner nbntv.com.au###sidebar_banner1 bestweekever.tv###sidebar_buzzfeed thinkdigit.com###sidebar_container[style="padding-top:0px !important; "] moneymakerdiscussion.com###sidebar_container[style="width: 200px;"] destructoid.com###sidebar_dad destructoid.com###sidebar_dad_contact forbes.com###sidebar_follower motorcycle.com###sidebar_leaderboard dzone.com,poponthepop.com###sidebar_rectangle icanhascheezburger.com###sidebar_scraper doityourself.com###sidebar_text_link_container smashingmagazine.com###sidebaradtarget webupd8.org###sidebard-top-wrapper racingweb.co.za###sidebarfrontright polodomains.com###sidebarin opendocument.xml.org###sidebarright dooce.com###sidebarskyholder quickonlinetips.com###sideboxfeature3 saportareport.com###sidetopleft sikids.com###sifk_topper zerohedge.com###similar-box imagebunk.com###simplemodal-container imagebunk.com###simplemodal-overlay businessweek.com###simplyHired fastcocreate.com###site-header we7.com###site-right kiplinger.com###site-sponsor knucklesunited.com###site-title opendemocracy.net###site-topbanner kstp.com###siteHeaderLeaderboard arsenal-mania.com###sitePromos reddit.com###siteTable_organic texastribune.org###site_roofline cybergamer.com###site_skin cybergamer.com###site_skin_spacer smsfun.com.au###sitebanners slashdot.org###sitenotice torrenttree.com###sites_right allmyvids.de###sitewide160right 2oceansvibe.com,djmag.co.uk,djmag.com,expertreviews.co.uk,mediaite.com,pcpro.co.uk,race-dezert.com###skin collegehumor.com,dorkly.com###skin-banner jest.com###skin_banner idg.com.au###skin_bump animenewsnetwork.com###skin_header animenewsnetwork.com###skin_left fleshbot.com###skin_wrap bit-tech.net###skinclick n4g.com###skinlink metalinjection.net###skinoverlay kovideo.net###skip dafont.com,dealchecker.co.uk,play.tm,torrent-finder.info,yellowpages.com.my###sky skytv.co.nz###sky-banner aol.co.uk,skysports.com###sky-bet-accordian homeportfolio.com###sky-bottom moneysupermarket.com###sky-container capitalfm.com,heart.co.uk###sky1 totalfilm.com###skyContainer itpro.co.uk###skyScraper expertreviews.co.uk,pcpro.co.uk###skyScrapper expertreviews.co.uk###skyScrapper2 nickydigital.com###sky_scrapper webopedia.com###skypartnerset ebay.co.uk,ebay.com,ebay.com.au###skyscrape 975countrykhcm.com,boomerangtv.co.uk,broadcastingcable.com,bustedcoverage.com,camchat.org,consumerist.com,eurogamer.net,family.ca,ghanaweb.com,hypable.com,king-mag.com,law.com,macuser.co.uk,menshealth.com,metrotimes.com,mp3tag.de,newsdaily.com,nme.com,pcworld.com,politics.co.uk,poponthepop.com,sportfishingbc.com,thehollywoodgossip.com,thesmokinggun.com,tmz.com,topgear.com,torontosun.com,tvfanatic.com,ucomparehealthcare.com,uncut.co.uk,victoriaadvocate.com,zerochan.net###skyscraper 4teachers.org###skyscraper-container s1jobs.com###skyscraper-target icanhascheezburger.com,ifans.com###skyscraper1 ifans.com###skyscraper2 jokes2go.com###skyscraperDiv familyfun.go.com###skyscraperIframeContainer prevention.com###skyscraperWrap nitrome.com,pri.org###skyscraper_box globrix.com,totalfilm.com###skyscraper_container m-w.com###skyscraper_creative_2 nitrome.com###skyscraper_description nitrome.com###skyscraper_shadow humanevents.com###skyscraperbox alloaadvertiser.com,ardrossanherald.com,ayradvertiser.com,barrheadnews.com,bordertelegraph.com,bracknellnews.co.uk,carrickherald.com,centralfifetimes.com,clydebankpost.co.uk,cumnockchronicle.com,dumbartonreporter.co.uk,eastlothiancourier.com,greenocktelegraph.co.uk,helensburghadvertiser.co.uk,irvinetimes.com,largsandmillportnews.com,localberkshire.co.uk,newburyandthatchamchronicle.co.uk,peeblesshirenews.com,readingchronicle.co.uk,sloughobserver.co.uk,strathallantimes.co.uk,the-gazette.co.uk,thevillager.co.uk,troontimes.com,windsorobserver.co.uk###skyscrapers bustedcoverage.com,xdafileserver.nl###skyscrapper computerandvideogames.com,officialnintendomagazine.co.uk,oxm.co.uk###skyslot sevenload.com###skyyscraperContainer allexperts.com,gifts.com###sl housebeautiful.com###sl_head gifts.com###slbox mobafire.com###slide-up bluff.com,bluffmagazine.com###slideBanner timesfreepress.com###slidebillboard roseindia.net###slidebox live365.com###slider yellowpagesofafrica.com###sliderPub hktdc.com###sliderbanner thephuketnews.com###slides yellowpageskenya.com###slideshow cio.com.au###slideshow_boombox 790kspd.com###slideshowwidget-8 bizrate.com###slimBannerContainer mail.yahoo.com###slot_LREC mail.yahoo.com###slot_MB mail.yahoo.com###slot_REC connectionstrings.com###slot_bottom connectionstrings.com###slot_leftmenu connectionstrings.com###slot_top connectionstrings.com###slotfirstpage uploadc.com,zalaa.com###slowcodec washingtonpost.com###slug_88x31 newsweek.com###slug_bigbox washingtonpost.com###slug_featured_links washingtonpost.com###slug_flex_ss_bb_hp washingtonpost.com###slug_inline_bb washingtonpost.com###slug_sponsor_links_rr sportsmole.co.uk###sm_shop dailyrecord.co.uk###sma-val-service ikascore.com###smalisted unfinishedman.com###smartest-banner-2 reviewjournal.com###smedia-upickem_deals_widget powerpointstyles.com###smowtion300250 pedestrian.tv###snap denverpost.com###snowReportFooter tfportal.net###snt_wrapper thepiratebay.se###social + a > img cioupdate.com,webopedia.com###solsect knowyourmeme.com###sonic sensis.com.au###southPfp stv.tv###sp-mpu-container kat.ph###sp2 aol.com###spA thedailygreen.com###sp_footer collegefashion.net###spawnsers torontolife.com###special-messages geeksaresexy.net###special-offers news.com.au###special-promotion bidnessetc.com###specialBox10 videogamer.com###specialFeatures countryliving.com###specialOffer countryliving.com###special_offer redbookmag.com###special_offer_300x200 cboe.com###special_offers pcmag.com###special_offers_trio winrumors.com###specialfriend totallycrap.com###specials rapid4me.com###speed_table pricegrabber.co.uk###spl filestube.to###spla fxempire.com###splash_over fxempire.com###splash_wraper aol.com###splink aol.com###splinkRight winsupersite.com###splinkholder cnet.com,howdesign.com###splinks realestate.aol.com###splinktop delicious.com###spns katz.cd###spon eweek.com###spon-con eweek.com###spon-list diynetwork.com###spon-recommendations dailyhaha.com###spon300 krillion.com###sponCol rockdizfile.com###spon_down rockdizfile.com###spon_down2 foreignpolicy.com###spon_reports quakelive.com###spon_vert phonescoop.com###sponboxb ninemsn.com.au###spons_left baseball-reference.com,breakingtravelnews.com,christianpost.com,compfight.com,europages.co.uk,itweb.co.za,japanvisitor.com,katu.com,komonews.com,lmgtfy.com,mothering.com,neave.com,otcmarkets.com,telegeography.com,tsn.ca,tvnz.co.nz,wallpapercropper.com,walyou.com,wgr550.com,wsjs.com,yahoo.com###sponsor leedsunited.com###sponsor-bar detroitnews.com###sponsor-flyout meteo-allerta.it,meteocentrale.ch,meteozentral.lu,severe-weather-centre.co.uk,severe-weather-ireland.com,vader-alarm.se###sponsor-info publicfinanceinternational.org###sponsor-inner itweb.co.za###sponsor-logo zymic.com###sponsor-partners talktalk.co.uk###sponsor-search friendster.com###sponsor-wrap americanidol.com###sponsorLogos ohio.com###sponsorTxt mlb.com###sponsor_container football-league.co.uk###sponsor_links health365.com.au###sponsor_logo_s lmgtfy.com###sponsor_wrapper 7search.com,espn.go.com,filenewz.com,general-fil.es,general-files.com,generalfil.es,independent.ie,internetretailer.com,ixquick.co.uk,ixquick.com,nickjr.com,rewind949.com,slickdeals.net,startpage.com,webhostingtalk.com,yahoo.com###sponsored theweathernetwork.com###sponsored-by webhostingtalk.com###sponsored-clear chacha.com###sponsored-question fbdownloader.com###sponsored-top lastminute.com###sponsoredFeature lastminute.com###sponsoredFeatureModule theblaze.com###sponsored_stories businessweek.com###sponsored_video smashingmagazine.com###sponsorlisttarget abalive.com,abestweb.com,barnsleyfc.co.uk,bbb.org,bcfc.com,bestuff.com,blackpoolfc.co.uk,burnleyfootballclub.com,bwfc.co.uk,cafc.co.uk,cardiffcityfc.co.uk,christianity.com,cpfc.co.uk,dcfc.co.uk,easternprovincerugby.com,etftrends.com,fastseduction.com,geekwire.com,gerweck.net,goseattleu.com,hullcitytigers.com,iconfinder.com,itfc.co.uk,kiswrockgirls.com,landreport.com,law.com,lcfc.com,manutd.com,myam1230.com,noupe.com,paidcontent.org,pba.com,pcmag.com,petri.co.il,pingdom.com,psl.co.za,race-dezert.com,rovers.co.uk,sjsuspartans.com,soompi.com,sponsorselect.com,star883.org,tapemastersinc.net,techmeme.com,trendafrica.co.za,waronyou.com,whenitdrops.com###sponsors sanjose.com###sponsors-module und.com###sponsors-story-wrap und.com###sponsors-wrap techie-buzz.com###sponsors2 netchunks.com###sponsorsM feedly.com###sponsorsModule_part clubwebsite.co.uk###sponsors_bottom wrc.com###sponsorsbtm ibtimes.com,npr.org,pbs.org###sponsorship backstage.com###sponsorsmod cnet.com###spotBidHeader cnet.com###spotbid mangafox.me###spotlight memory-alpha.org###spotlight_footer justdubs.tv###spots qj.net###sqspan zam.com###square-box allakhazam.com###square-box:first-child comicbookmovie.com###squareATF newsonjapan.com###squarebanner300x250 rent.ie###sresult_banner realestate.yahoo.com###srp-ysm gifts.com###srp_sl fun.familyeducation.com,genealogy.familyeducation.com,infoplease.com###ssky saharareporters.com###stage-header businessdictionary.com###standalone_text milb.com###standard_banner cucirca.eu###stanga alternativeto.net###startpage-right capitalfm.com.my###stationbannersliderwrapper rally24.com###stickedPanel gizchina.com###sticky-anchor gizchina.com###sticky-anchor-right propakistani.pk###sticky_banner2 ncregister.com###sticky_box retronintendogames.com###sticky_footer stltoday.com###stl-below-content-02 dailypuppy.com###stop_puppy_mills someecards.com###store marketwatch.com###story-premiumbanner dailyherald.com###storyMore cbc.ca###storymiddle instyle.co.uk###style_it_light_ad praag.org###sub-header discovermagazine.com###sub-portlet wjunction.com###subBar ubergizmo.com###sub_footer usmagazine.com###sub_form_popup mayoclinic.com###subbox msn.com,theatlantic.com###subform dallasvoice.com,dealerscope.com,gamegrep.com,winamp.com###subheader foodandwine.com###subscModule macworld.com,pcworld.com###subscribeForm vg247.com###subuffer hollywire.com###super-header chicagomag.com###super-leaderboard-wrapper detroitnews.com###super-widget disney.go.com###superBanner wondertime.go.com###superBannerContainer ugo.com###superMast v3.co.uk###superSky sevenload.com###superbaannerContainer canoe.ca,free-css.com,wral.com###superbanner dzone.com###superboard shacknews.com###superleader news.com.au###superskin totalfilm.com###supersky_container mediaite.com###supertop dashnet.org###support marketplace.org###support_block_side macnn.com###supportbod marketwatch.com###supposedlytemporaryad mail.yahoo.com###swPane edmunds.com###sway-banner epicurious.com###sweepstakes picp2.com###system unlockboot.com###t-banner mma-core.com###ta_pnlAd livescore.in###tab-bonus-offers flashscore.com,livescore.in###tab-odds ipmart-forum.com###table1 dropvideo.com###table1[width="100%"][height="100%"][border="0"] saynoto0870.com###table2[bordercolor="#000000"] macupdate.com###table_bot_l fulldls.com###table_filter + .torrent_table atdhe.eu###table_linky:last-child > thead:first-child torrentzap.com###table_self movie2k.tl###tablemoviesindex > tbody:first-child:last-child > tr:last-child movie4k.to###tablemoviesindex:last-child > tbody:first-child:last-child > tr:last-child rgj.com###taboola-column-c-new-google crystalmedianetworks.com###tabs_banner shorpy.com###tad bediddle.com###tads google.com###tadsc ajaxian.com###taeheader anilinkz.tv###tago esquire.com,meetme.com,muscleandfitness.com,techvideo.tv###takeover techvideo.tv###takeover-spazio nme.com###takeover_head nme.com###takeover_left channel5.com###takeover_link nme.com###takeover_right broadbandgenie.co.uk,thesun.co.uk###takeoverleft broadbandgenie.co.uk,thesun.co.uk###takeoverright boardgamegeek.com###tanga taste.com.au###taste-right-banner runescape.com###tb manchesterconfidential.co.uk###tb_bnr baltictimes.com###tbt_system_note thesaurus.com###tcomad_728x90_0 saleminteractivemedia.com###td_leaderboard listenlive.co###td_leaderboard_wrapper news.aol.co.uk###tdiv60 aol.co.uk###tdiv71 news.aol.co.uk###tdiv74 independent.co.uk###tertiaryColumn > .slider diablo3builds.com,financialsurvivalnetwork.com,popbytes.com###text-10 geeky-gadgets.com###text-105335641 newsfirst.lk###text-106 couponistaqueen.com,dispatchlive.co.za###text-11 callingallgeeks.org,cathnews.co.nz,myx.tv,omgubuntu.co.uk###text-12 cleantechnica.com###text-121 airlinereporter.com,myx.tv,omgubuntu.co.uk,radiosurvivor.com,wphostingdiscount.com###text-13 dispatchlive.co.za,krebsonsecurity.com,myx.tv,omgubuntu.co.uk,planetinsane.com###text-14 razorianfly.com###text-155 gizchina.com,thesurvivalistblog.net###text-16 englishrussia.com,thechive.com###text-17 delimiter.com.au###text-170 netchunks.com,planetinsane.com,radiosurvivor.com,sitetrail.com,thechive.com###text-18 delimiter.com.au###text-180 delimiter.com.au###text-189 collective-evolution.com,popbytes.com,thechive.com###text-19 delimiter.com.au###text-192 delimiter.com.au###text-195 businessdayonline.com,callingallgeeks.org,financialsurvivalnetwork.com###text-21 airlinereporter.com,callingallgeeks.org,gizchina.com,omgubuntu.co.uk,queenstribune.com###text-22 omgubuntu.co.uk,queenstribune.com###text-23 queenstribune.com###text-24 netchunks.com###text-25 2smsupernetwork.com,pzfeed.com,queenstribune.com###text-26 2smsupernetwork.com,sonyalpharumors.com###text-28 beijingcream.com###text-29 2smsupernetwork.com,airlinereporter.com,buddyhead.com,mbworld.org,zambiareports.com###text-3 sonyalpharumors.com###text-31 techhamlet.com###text-32 couponistaqueen.com,pzfeed.com###text-35 couponistaqueen.com###text-38 pzfeed.com###text-39 budapesttimes.hu,buddyhead.com,dieselcaronline.co.uk,knowelty.com,myonlinesecurity.co.uk,myx.tv,sportsillustrated.co.za,theairportnews.com,thewhir.com###text-4 couponistaqueen.com###text-40 enpundit.com###text-41 pluggd.in###text-416180296 pluggd.in###text-416180300 bigblueball.com###text-416290631 eurweb.com###text-42 defensereview.com###text-460130970 thebizzare.com###text-461006011 thebizzare.com###text-461006012 spincricket.com###text-462834151 enpundit.com###text-48 pencurimovie.cc###text-49 myx.tv,washingtonindependent.com###text-5 2smsupernetwork.com,rawstory.com###text-50 quickonlinetips.com###text-57 2smsupernetwork.com,couponistaqueen.com,englishrussia.com,mynokiablog.com,myx.tv,pakladies.com,times.co.zm,trendafrica.co.za,washingtonindependent.com###text-6 buddyhead.com,defsounds.com,knowelty.com,prosnookerblog.com,technomag.co.zw###text-7 consortiumnews.com,couponistaqueen.com,michiganmessenger.com,newsday.co.zw,technomag.co.zw###text-8 mynokiablog.com###text-9 torontolife.com###text-links washingtonpost.com###textlinkWrapper the217.com###textpromo teamandroid.com###tf_header teamandroid.com###tf_sidebar_above teamandroid.com###tf_sidebar_below teamandroid.com###tf_sidebar_skyscraper1 teamandroid.com###tf_sidebar_skyscraper2 notebookreview.com###tg-reg-ad mail.yahoo.com###tgtMNW girlsaskguys.com###thad thatscricket.com###thatscricket_google_ad yahoo.com###theMNWAd rivals.com###thecontainer duoh.com###thedeck thekit.ca###thekitadblock thonline.com###thheaderadcontainer theberry.com,thechive.com###third-box videobam.com###this-pays-for-bandwidth-container ticketmaster.com###thisSpon lyricsfreak.com###ticketcity yahoo.com###tiles-container > #row-2[style="height: 389.613px; padding-bottom: 10px;"] rte.ie###tilesHolder distro.megom.tv###timeNumer tinypaste.com###tinychat_lightbox tinypaste.com###tinychat_overlay yourweather.co.uk###titulo myspace.com###tkn_leaderboard myspace.com###tkn_medrec placehold.it###tla fileinfo.com###tlbspace timeoutabudhabi.com,timeoutbahrain.com,timeoutdoha.com,timeoutdubai.com###tleaderb thelifefiles.com###tlfAdInBetween300x250 imdb.com###tn15adrhs technewsworld.com###tnavad omgubuntu.co.uk###to-top chattanooganow.com###toDoWrap megavideoshows.com###toHide toonix.com###toonix-adleaderboard iconeye.com,phonescoop.com,politics.co.uk,reference.com,thesaurus.com,topcultured.com###top jillianmichaels.com,synonym.com###top-300 xxlmag.com###top-728x90 techiemania.com###top-729-banner freemake.com###top-advertising chip.eu,corkindependent.com,dancehallreggae.com,ebuddy.com,foodlovers.co.nz,galwayindependent.com,inthenews.co.uk,investorplace.com,itweb.co.za,lyrics19.com,maclife.com,maximumpc.com,politics.co.uk,scoop.co.nz,skift.com,techi.com,thedailymash.co.uk,thespiritsbusiness.com,timesofisrael.com,tweaktown.com###top-banner scoop.co.nz###top-banner-base theberrics.com###top-banner-container krebsonsecurity.com###top-banner-image krebsonsecurity.com###top-banner-img privatehealth.co.uk###top-banner-outer autotrader.ie,carzone.ie###top-banner-placeholder if-not-true-then-false.com###top-banner-wrapper panorama.am###top-banners missingremote.com,timesofisrael.com###top-bar wfgo.net,wtso.tv###top-bn teesoft.info###top-bottom whowhatwear.com###top-container jacksonville.com###top-header aspensojourner.com###top-layer canstar.com.au###top-lb joystiq.com###top-leader cantbeunseen.com,chairmanlol.com,diyfail.com,explainthisimage.com,fayobserver.com,funnyexam.com,funnytipjars.com,gamejolt.com,iamdisappoint.com,japanisweird.com,morefailat11.com,objectiface.com,passedoutphotos.com,perfectlytimedphotos.com,roulettereactions.com,searchenginesuggestions.com,shitbrix.com,sparesomelol.com,spoiledphotos.com,stopdroplol.com,tattoofailure.com,yodawgpics.com,yoimaletyoufinish.com###top-leaderboard smarterfox.com###top-left-banner sportinglife.com###top-links politiken.dk###top-monster dubizzle.com###top-mpu canstar.com.au###top-mrec ovationtv.com###top-promo inman.com###top-pusher imassera.com,thebestdesigns.com###top-sponsor suntimes.com###top1 meteovista.co.uk###top10 gamingzion.com###top10c moviecarpet.com###top728 investmentnews.com###topAdBlock americanscientist.org,auctiva.com,cartoonnetwork.co.nz,cartoonnetwork.com.au,cartoonnetworkasia.com,eweek.com,filesfrog.com,freecsstemplates.org,geeksailor.com,gizgag.com,highestfive.com,nerve.com,nzherald.co.nz,plosbiology.org,port2port.com,quotesdaddy.com,sciencemag.org,tastemag.co.za###topBanner cntraveler.com###topBanner728x90_frame danpatrick.com,microsoft-watch.com###topBannerContainer macworld.co.uk###topBannerSpot money.co.uk###topBar ewn.co.za###topCoke atlasobscura.com###topContainer kioskea.net###topContent cnet.com###topDownloads popularscreensavers.com###topFooter scoop.co.nz###topHeader chacha.com###topHeaderBannerWrap thecitizen.co.tz###topLeaderBoard digitalartsonline.co.uk,pcadvisor.co.uk###topLeaderContainer donedeal.ie,kenyamoja.com,metrotimes.com,orlandoweekly.com,sacurrent.com,startribune.com,wjla.com###topLeaderboard kenyamoja.com###topLeaderboard + * + .container-bot autotrader.co.uk,fixya.com,topmarques.co.uk###topLeaderboardContainer chamberofcommerce.com###topLeaderboardParent teoma.com###topPaidList topsite.com###topRightBunner prevention.com###topThirdPartyArea rockyou.com###topXpromoWrapper hardballtalk.nbcsports.com###top_90h theepochtimes.com###top_a_0d ytmnd.com###top_ayd boxoffice.com,computing.net,disc-tools.com,goldentalk.com,guyspeed.com,hemmings.com,imagebam.com,magme.com,moono.com,phonearena.com,popcrush.com,sportsclimax.com,techradar.com,tidbits.com,venturebeatprofiles.com,webappers.com###top_banner caribpress.com###top_banner_container theimproper.com###top_banner_widget motorship.com###top_banners avaxsearch.com###top_block psdeluxe.com###top_bsa hemmings.com###top_dc_tbl bnd.com###top_jobs_footer centredaily.com###top_jobs_search bakersfield.com,bakersfieldcalifornian.com,dailypuppy.com,jamaicaobserver.com,proudfm.com,rushlimbaugh.com###top_leaderboard columbiatribune.com###top_leaderboard_pos computerworld.com###top_leaderboard_wrapper babylon.com,search.chatzum.com,searchsafer.com###top_links ninemsn.com.au###top_promo_ie8 smosh.com###top_promo_wrapper electricenergyonline.com,fotolog.com###top_pub mma-core.com###top_r_bans imdb.com###top_rhs_1_wrapper imdb.com###top_rhs_wrapper getlyrics.com###top_right escapistmagazine.com###top_site_part humanevents.com###top_skyscraperbox cellular-news.com###top_sq_block samoaobserver.ws###top_wrap1 arthritistoday.org###topads btimes.com.my###topadv scorespro.com###topban absolutelyrics.com,artima.com,bbyellow.com,bsyellow.com,businessdirectory.mu,businesslist.ae,businesslist.co.cm,businesslist.co.ke,businesslist.co.ug,businesslist.com.bd,businesslist.com.ng,businesslist.hk,businesslist.my,businesslist.net.nz,businesslist.ph,businesslist.pk,businesslist.sg,businesslist.tw,businesslist.vn,caymanyellow.com,checkoutmyink.com,chictopia.com,chileindex.com,colombiayp.com,dominicanyp.com,dumpalink.com,egypyp.com,ethiopiadirectory.com,exiledonline.com,findtheword.info,georgiayp.com,ghanayp.com,hiphongkong.com,icenews.is,indonesiayp.com,jmyellow.com,jpyellow.com,lebyp.com,lesothoyp.com,localbotswana.com,malawiyp.com,medicaldaily.com,moroccoyp.com,myanmaryp.com,namibiayp.com,nation.lk,onlinebusinesslist.co.za,plosone.org,puertoricoindex.com,qataryp.com,realitywanted.com,rwandayp.com,saudianyp.com,senegalyp.com,sierraexpressmedia.com,snapfiles.com,sudanyp.com,tanzaniayp.com,tcmagazine.com,tcmagazine.info,thaigreenpages.com,thedigitalfix.com,thehill.com,thevarguy.com,tntyellow.com,tremolo.edgesuite.net,tunisiayp.com,turkishyp.com,venezuelayp.com,vocm.com,webattack.com,wenn.com,workswithu.com,wzmetv.com,xbox360rally.com,yemenyp.com,zambiayp.com,zimbabweyp.com,zipinfo.in###topbanner drugs.com###topbannerWrap checkoutmyink.com###topbanner_div chictopia.com###topbanner_pushdown littlegreenfootballs.com###topbannerdiv snapfiles.com###topbannermain eatsleepsport.com,soccerphile.com,torrentpond.com###topbanners swedishwire.com###topbannerspace ilix.in,newtechie.com,postadsnow.com,songspk.link,songspk.name,textmechanic.com,thebrowser.com,tota2.com###topbar newsbusters.org###topbox thecrims.com###topbox_content educatorstechnology.com###topcontentwrap bhg.com###topcover football411.com###topheader tvembed.eu###toplayerblack usingenglish.com###topleader joystiq.com,luxist.com,massively.com,switched.com,wow.com###topleader-wrap bannedinhollywood.com,eventhubs.com,shopcrazy.com.ph###topleaderboard celebitchy.com###topline microcosmgames.com###toppartner macupdate.com###topprommask worldtimebuddy.com###toprek tbo.com###topslider plos.org###topslot thespacereporter.com###topster codingforums.com###toptextlinks inquisitr.com###topx2 dinozap.tv,hdcastream.com,hdmytv.com###total dinozap.tv,hdmytv.com###total_banner pgatour.com###tourPlayer300x250BioAd vimeo.com###tout_rotater pcworld.com###touts.module garfield.com###tower electricenergyonline.com###tower_pub phonescoop.com###towerlinks oncars.com###towers under30ceo.com###tptopbar technologyreview.com###tr35advert indowebster.com###tr_iklanbaris2 marketwatch.com###tradingcenter telegraph.co.uk###trafficDrivers mapquest.com###trafficSponsor channelregister.co.uk###trailer genevalunch.com###transportation dallasnews.com###traveldeals people.com###treatYourself bitcoin.cz###trezor miroamer.com###tribalFusionContainer sitepoint.com###triggered-cta-box-wrapper wigflip.com###ts-newsletter forums.techguy.org###tsg-dfp-300x250 forums.techguy.org###tsg-dfp-between-posts tsn.ca###tsnHeaderAd tsn.ca###tsnSuperHeader macworld.com,pcworld.com,techhive.com###tso pcmag.com###tswidget teletoon.com###tt_Sky tumblr.com###tumblr_radar.premium tvlistings.theguardian.com###tvgAdvert tvsquad.com###tvsquad_topBanner weather.com###twc-partner-spot twit.tv###twit-ad-medium-rectangle imageporter.com,imgspice.com###txtcht howtogetridofstuff.com###tz_rwords direct-download.org###u539880 careerbuilder.com###uJobResultsAdTopRight2_mxsLogoAds__ctl0_CBHyperlink1 yahoo.com###u_2588582-p kuklaskorner.com###ultimate theaa.com###unanimis1 snagajob.com###underLeftSponsor worldwideweirdnews.com###underarticle jumptogames.com###underrandom pcworld.com,teesoft.info###uniblue reminderfox.org###uniblueImg geekosystem.com###unit-area gossipcop.com,mediaite.com,themarysue.com###unit-footer styleite.com,thebraiser.com###unit-header sportsgrid.com###unit-sidebar thebraiser.com###unit-sidebar-atf styleite.com,thebraiser.com###unit-sidebar-btf intothegloss.com###unit250 intothegloss.com###unit600 notebook-driver.com###updatemydrivers carionltd.com###upmapads byutvsports.com###upper-poster comingsoon.net###upperPub usanetwork.com###usa_desktop downloadhelper.net###useful-tools torrentpond.com###usenet-container fulldls.com###usenetb popcap.com###vacquest_overlay popcap.com###vacquest_window armyrecognition.com###vali2 hipforums.com###vbp_banner_82 hipforums.com###vbp_banner_foot hipforums.com###vbp_banner_head listentoyoutube.com###vc_top_ad filespart.com###vdwd30 tv.com###vendor_spotlight popeater.com###verizonPromo temptalia.com###vert-boxes chud.com###vertical.ad standard.co.uk###viagogo-all-events theedge.co.nz###vidBanner cnbc.com###vidRightRailWrapper ibrod.tv###video cricket.yahoo.com###video-branding mentalfloss.com###video-div-polo youtube.com###video-masthead cartoonnetworkasia.com###videoClip-main-right-ad300Wrapper-ad300 radaronline.com###videoExternalBanner video.aol.com###videoHatAd radaronline.com###videoSkyscraper techradar.com###viewBestDealsWrapper europages.co.uk###vipBox gumtree.sg###vip_all_r1_300x250 gumtree.sg###vip_all_r2_300x60 gumtree.sg###vip_all_r3_300x60 miami.com###visit news24.com###vitabox-widget animeflv.net,tubeplus.me###vlc episodeninja.com,pspmaniaonline.com###vnealveaijvanef eatingwell.com###vs4-tags search.mywebsearch.com###vsaTop + div[id] search.mywebsearch.com###vsaTop + div[id] + div[id] nickjr.com###vsw-container-wrapper nickjr.com###vsw-medium-outter nickjr.com###vsw-small-outter skysports.com###w10-banner variety.com###w300x250 weatherbug.co.uk###wXcds2 weatherbug.co.uk###wXcds4 inquirer.net###wall_addmargin_left edmunds.com###wallpaper information-age.com###wallpaper-surround-outer eeweb.com###wallpaper_image thepressnews.co.uk###want-to-advertise nowtorrents.com###warn_tab youtube.com###watch-branded-actions youtube.com###watch-buy-urls youtube.com###watch-channel-brand-div nytimes.com###watchItButtonModule thefreedictionary.com###wb1 murga-linux.com###wb_Image1 sheridanmedia.com###weather-sponsor wkrq.com###weather_traffic_sponser kentonline.co.uk###weathersponsorlogo nzdating.com###webadsskydest cinewsnow.com###week-catfish mercurynews.com,santacruzsentinel.com###weeklybar2 linuxinsider.com###welcome-box mainstreet.com###welcomeOverlay phoronix.com###welcome_screen bellinghamherald.com,bradenton.com,carynews.com,centredaily.com,claytonnewsstar.com,fresnobee.com,heraldonline.com,idahostatesman.com,islandpacket.com,kentucky.com,lakewyliepilot.com,ledger-enquirer.com,lsjournal.com,macon.com,modbee.com,myrtlebeachonline.com,newsobserver.com,sanluisobispo.com,star-telegram.com,sunherald.com,thenewstribune.com,theolympian.com,thestate.com,tri-cityherald.com###wgt_dealsave_standalone theatlantic.com###whatreadingad sharkyforums.com,smallbusinesscomputing.com###whitePaperIFrame devshed.com,eweek.com###whitebox domaintools.com###whois-related-forsale spectrum.ieee.org###whtpprs ubi.com###wide-promo forexpros.com,investing.com###wideBanner inquirer.net###wideSidebar > .widget gomapper.com,politics.co.uk###wideSkyScraper linguee.com###wide_banner_right coupons.com###widesky-banner gigaom.com###widget-area-footer-post-2 howwemadeitinafrica.com###widget-r stltoday.com###widget-todays-deal technabob.com###widgetTable pcweenies.com###widgetTable[width="170"][bgcolor="#FFFFFF"] vikitech.com###widget_A eevblog.com###widget_linkmasterpro_ri-2 filesharingtalk.com###widgetlist_column1 > li:first-child + li + li:last-child > .cms_widget talksport.com###williamarticlelink search.pch.com###winner-list thaindian.com###withinsimilar staugustine.com###wl-wrapper-leaderboard staugustine.com###wl-wrapper-tier-4 pr0gramm.com###wm wallpapersmania.com###wm_cpa rediff.com###world_right1 rediff.com###world_top fansfc.com###worldcupspl_container_left asiansoundradio.com###wowslider-container2 asiansoundradio.com###wowslider-container3 bittorrent.com###wpcom_below_post washingtonpost.com###wpni_adi_leaderboard linksave.in###wrap > #menue + #menuelinks linksave.in###wrap > #menue:first-child documentary.net###wrapper > #horizontal-outer-widgets-1 strategyinformer.com###wrapper3 euractiv.com###wrapperHeader reference.com,thesaurus.com###wrapserp sootoday.com###wwSponsor post-trib.com###wwbncontainer 9news.com###wx-widget-88x31 davidwalsh.name###x-secondary robtex.com###xadt0 robtex.com###xadt1 forum.xda-developers.com###xda_header_announce_title maxthon.com###xds cnet.com###xfp_adspace robtex.com###xnad728 vrbo.com###xtad abconline.xyz###xydllc ople.xyz###xydlleft abconline.xyz###xydlrc ople.xyz###xydlright fancystreems.com,sharedir.com###y yahoo.com###y708-ad-lrec1 yahoo.com###y708-sponmid au.yahoo.com###y708-windowshade yahoo.com###y_provider_promo yahoo.com###ya-center-rail > [id^="ya-q-"][id$="-textads"] answers.yahoo.com###ya-darla-LDRB answers.yahoo.com###ya-darla-LREC answers.yahoo.com###ya-qpage-textads vipboxsports.eu,vipboxsports.me,viplivebox.eu,viponlinesports.eu###ya_layer sevenload.com###yahoo-container missoulian.com###yahoo-contentmatch independent.co.uk###yahooLinks yahoo.com###yahooPN_CM yellowpages.com###yahoo_ss_border yahoo.com###yahoovideo_ysmlinks autos.yahoo.com###yatadfin autos.yahoo.com###yatadfinbd autos.yahoo.com###yatadlrec autos.yahoo.com###yatadoem autos.yahoo.com###yatadoembd uproxx.com###yb-banner macintouch.com###yellows finance.yahoo.com###yfi_ad_FB2 finance.yahoo.com###yfi_ad_cl yahoo.com###yfi_pf_ysm yahoo.com###yfi_ysm yahoo.com###ygmapromo yahoo.com###yh-ysm yahoo.com###yl_pf_ysm yahoo.com###ylf-ysm shine.yahoo.com###ylf-ysm-side local.yahoo.com###yls-dt-ysm maps.yahoo.com###ymap_main_footer yahoo.com###ymh-invitational-recs yahoo.com###yn-darla2 yahoo.com###yn-gmy-promo-answers yahoo.com###yn-gmy-promo-groups trackthepack.com###yoggrt wfaa.com###yollarSwap afmradio.co.za###yourSliderId search.yahoo.com###ysch #doc #bd #results #cols #left #main .ads search.yahoo.com###ysch #doc #bd #results #cols #left #main .ads .left-ad search.yahoo.com###ysch #doc #bd #results #cols #left #main .ads .more-sponsors search.yahoo.com###ysch #doc #bd #results #cols #left #main .ads .spns search.yahoo.com###ysch #doc #bd #results #cols #right #east .ads yahoo.com###yschsec fancystreems.com,onlinemoviesgold.com,sharedir.com,stream2watch.com###yst1 travel.yahoo.com###ytrv-ysm-hotels travel.yahoo.com###ytrv-ysm-north travel.yahoo.com###ytrv-ysm-south travel.yahoo.com,travel.yahoo.net###ytrvtrt webmastertalkforums.com###yui-gen24[style="width: 100%; height: 100px !important;"] zynga.com###zap-bac-iframe bloomberg.com,post-gazette.com###zillow post-trib.com###zip2save_link_widget moreintelligentlife.com###zone-header hendersondispatch.com,heraldsun.com,hpe.com###zone-leaderboard italymagazine.com###zone-user-wrapper kovideo.net###zone0_top_banner_container hulkshare.com,rockyou.com###zone1 hulkshare.com###zone2 luxury-insider.com###zone_728x90 asfile.com###zone_bottom asfile.com###zone_top theonion.com###zoosk popcap.com###zrJungle1033_overlay popcap.com###zrJungle1033_window bing.com###zune_upsell teamfortress.tv###zuside teamfortress.tv###zutop facebook.com##.-cx-PRIVATE-fbAdUnit__root facebook.com##.-cx-PRIVATE-fbEmu__root facebook.com##.-cx-PRIVATE-fbFacebarTypeaheadToken__sponsored facebook.com##.-cx-PRIVATE-snowliftAds__root facebook.com##.-cx-PRIVATE-spyml__story facebook.com##.-cx-PUBLIC-fbAdUnit__root skysports.com##.-skybet-widget investopedia.com##.A1 realtor.com##.ADLB shoppinglifestyle.com##.ADV bendsource.com,bestofneworleans.com,bigskypress.com,cltampa.com,csindy.com,laweekly.com,realdetroitweekly.com,sevendaysvt.com,similarsites.com,styleweekly.com,tucsonweekly.com##.Ad footballitaliano.co.uk##.Ad1 filmsnmovies.com,redbalcony.com##.AdContainer verizon.com##.AdIn incyprus.com.cy##.Add1st oncars.in##.Adv colouredgames.com##.AdvGamesList irna.ir,journalofaccountancy.com,newvision.co.ug##.Advertisement europeantour.com,yedda.com##.Advertising hongkiat.com##.BAds terradaily.com##.BDTX hotklix.com##.BLK300 highstakesdb.com##.Banner acharts.us##.BannerConsole mixedmartialarts.com##.BannerRightCol natgeotv.com##.BannerTop truck1.eu,webresourcesdepot.com##.Banners stockopedia.co.uk##.BigSquare juxtapoz.com##.Billboard mustakbil.com##.Bottom728x90BannerHolder hot1045.net##.BottomBannerTD dailytech.com##.BottomMarquee freeiconsweb.com##.Bottom_Banner myps3.com.au##.Boxer[style="height: 250px;"] myrealgames.com##.CAdFlashPageTop728x90 myrealgames.com##.CAdGamelist160x600 myrealgames.com##.CAdOpenSpace336x280 myrealgames.com##.CAdOpenSpace728x90 myrealgames.com##.CCommonBlockGreen[style="width: 630px;"] thebull.com.au##.Caja_Der clashdaily.com##.ClashDaily_728x90_Single_Top ljworld.com,newsherald.com##.DD-Widget archdaily.com##.DFP-banner forbes.com##.DL-ad-module healthzone.pk##.DataTDDefault[width="160"][height="600"] israeltoday.co.il##.DnnModule-1143 secdigitalnetwork.com##.DnnModule-6542 secdigitalnetwork.com##.DnnModule-6547 israeltoday.co.il##.DnnModule-758 israeltoday.co.il##.DnnModule-759 diet.com##.Fine mainjustice.com##.FirstHeader similarsites.com,topsite.com##.FooterBanner 969therock.com,993thevibe.com,wfls.com##.Footer_A_Column artistdaily.com##.FreemiumContent popmatters.com##.FrontPageBottom728 google.co.uk##.GBTLFYRDM0 google.com##.GC3LC41DERB + div[style="position: relative; height: 170px;"] google.com##.GGQPGYLCD5 google.com##.GGQPGYLCMCB google.com##.GISRH3UDHB orkut.com##.GLPKSKCL free-games.net##.GamePlayleaderboardholder bloemfonteincourant.co.za##.HPHalfBanner u.tv##.Header-Menu-Sponsor walmart.com##.IABHeader safehaven.com##.IAB_fullbanner safehaven.com##.IAB_fullbanner_header sierraexpressmedia.com##.IBA inc.com##.IMU-Container footytube.com##.InSkinHide smartearningsecrets.com##.Intercept-1 islamicfinder.org##.IslamicData[bgcolor="#FFFFFF"][bordercolor="#ECF3F9"] bloemfonteincourant.co.za,ofm.co.za,peoplemagazine.co.za##.LeaderBoard morningstar.com##.LeaderWrap agrieco.net,fjcruiserforums.com,mlive.com,newsorganizer.com,oxygenmag.com,urgames.com##.Leaderboard op.gg##.LifeOwner myabc50.com,whptv.com,woai.com##.LinksWeLike animenova.tv,animetoon.tv,gogoanime.com,goodanime.eu,gooddrama.net,toonget.com##.MClose timeout.com##.MD_textLinks01 mangahere.co##.MHShuffleAd hsj.org##.ML_L1_ArticleAds mstar.com##.MPFBannerWrapper expressandstar.com,juicefm.com,planetrock.com,pulse1.co.uk,pulse2.co.uk,shropshirestar.com,signal1.co.uk,signal2.co.uk,sportal.co.nz,sportal.com.au,swanseasound.co.uk,thewave.co.uk,three.fm,wave965.com,wirefm.com,wishfm.net##.MPU foxafrica.com##.MPU300 foxafrica.com,foxcrimeafrica.com,fxafrica.tv##.MPU336 three.fm##.MPURight dubaieye1038.com##.MPU_box dubai92.com,virginradiodubai.com##.MPU_box-innerpage virginradiodubai.com##.MPU_box_bottom thepittsburghchannel.com##.MS search.aol.com##.MSL + script + script + div[class] > style + script + h3[class] videowing.me##.MadDivtuzrfk videowing.me##.MadDivtuzrjt thebull.com.au##.Maquetas juxtapoz.com##.MarketPlace farmersweekly.co.za##.MasterLeaderboard totaltele.com##.Master_LargeMPU agrieco.net##.MedRect bloemfonteincourant.co.za,ofm.co.za##.MediumRectangle iwsearch.net##.Mid-Top alienbomb.com##.Middle468x60 mustakbil.com##.Middle728x90BannerHolder worldtribune.com##.NavMenu 4shared.com##.Nbanner tribe.net##.OAS nytimes.com##.OB_AR_1 artistdaily.com##.OFIEContent sofeminine.co.uk##.OffresSpe_cadre majorgeeks.com##.Outlines thefreedictionary.com##.Ov starsue.net##.OyunReklam webgurubb.com##.PCN-banner-zone search.aol.co.uk,search.aol.com##.PMB diamscity.com##.PUB_72890_TOP agonybooth.com##.PWAd twogag.com##.PWhalf gmx.co.uk##.PanelPartners popstoptv.com##.PeerFly_Banners priceme.co.nz##.ProductAdr i4u.com##.Promo peoplemagazine.co.za##.R300x250 peoplemagazine.co.za##.R300x600 huffingtonpost.com,search.aol.com##.RHRSLL search.aol.com##.RHRSLLwseboF bitcandy.com##.RR_adv ehow.com##.RadLinks japantimes.co.jp##.RealEstateAdBlock algoafm.co.za##.RightBanner1 algoafm.co.za##.RightBanner2 algoafm.co.za##.RightBanner3 algoafm.co.za##.RightBanner4 camfuze.com##.RightBannerSpot b105.com##.RotatingPromo_300x80 ebay.co.uk,ebay.com.au##.RtmStyle aolsearch.com,search.aol.ca,search.aol.co.uk,search.aol.com,search.aol.in,wow.com##.SLL search.aol.com##.SLLwseboF lifespy.com##.SRR theeagle.com##.SectionRightRail300x600Box memory-alpha.org,wikia.com##.SelfServeUrl similarsites.com##.SidebarBanner adobe.com##.SiteFooterRow[style="font-size:9px;font-family:Arial"] myspace.com##.SitesMedRecModule pdfzone.com##.Skyscraper_BG japantimes.co.jp##.SmallBanner car.com##.SmallFont mdlinx.com##.Sponsor-Tag hotscripts.com##.Sponsored mining.com##.SponsoredPost futureclaw.com##.Sponsors zone.msn.com##.SuperBannerTVMain shopping.canoe.ca##.SuperBoxDetails testcountry.com##.TC_advertisement yahoo.com.au##.TL_genericads_columns yahoo.com.au##.TL_medRec_container geekzone.co.nz##.TPconfmed1x4outer istockanalyst.com##.TelerikModalOverlay adobe.com##.TextSmall[align="center"][style="font-size:9px;font-family:Arial"] algoafm.co.za,hurriyetdailynews.com,ocweekly.com##.TopBanner hurriyetdailynews.com##.TopNews theday.com##.TopNewsSponsor torrentbar.com##.Tr2[width="41%"] japantimes.co.jp##.UniversitySearchAdBlock 1003thepoint.com,949thebay.com,radioeagleescanaba.com,radioeaglegaylord.com,radioeaglemarquette.com,radioeaglenewberry.com,radioeaglesoo.com,straitscountry953.com##.VGC_BANNER vh1.com##.VMNThemeSidebarWidget zone.msn.com##.VerticalBannerTV_tag browardpalmbeach.com,citypages.com,dallasobserver.com,houstonpress.com,laweekly.com,miaminewtimes.com,ocweekly.com,phoenixnewtimes.com,riverfronttimes.com,sfweekly.com,villagevoice.com,westword.com##.VoiceDealOfTheDayImage search.aol.ca,search.aol.co.uk,search.aol.com##.WOL search.aol.com##.WOL2 webreference.com##.WRy1 wzzk.com##.Weather_Sponsor_Container bloemfonteincourant.co.za,ofm.co.za##.WideSkyscraper wired.com##.WiredWidgetsMarketing xbox.com##.XbcSponsorshipText rxlist.com##.Yahoo facebook.com##._24n facebook.com##._24o juxtapoz.com##._300x250 facebook.com##._3qj- facebook.com##._4u8 filenuke.net,filmshowonline.net,fleon.me,hqvideo.cc,putlocker.ws,sharesix.net,skylo.me,streamme.cc,vidshare.ws##._ccctb crawler.com##.a lawyersweekly.com.au##.a-center anime1.com,drama.net##.a-content eplsite.com##.a-el krebsonsecurity.com##.a-statement daijiworld.com##.a2 knowyourmeme.com##.a250x250 cnet.com##.a2[style="padding-top: 20px;"] gematsu.com,twitch.tv,twitchtv.com##.a300 animeid.com,makeagif.com##.a728 localtiger.com##.a9gy_lt hereisthecity.com##.aLoaded tvnz.co.nz##.aPopup legacy.com##.aa_Table mmorpg.com##.abiabnotice four11.com##.abig k9safesearch.com##.ablk four11.com##.ablock four11.com##.ablock_leader four11.com##.ablock_right tribalfootball.com##.above-footer-wrapper likwidgames.com##.aboveSiteBanner urlfan.com##.abox filedir.com##.abox300 msn.com,search.yahoo.com##.abs whirlpool.net.au##.abvertibing_block thefreedictionary.com##.ac dailyrecord.co.uk##.ac-vehicle-search au.news.yahoo.com##.acc-moneyhound goseattleu.com##.accipiter consequenceofsound.net##.acm-module-300-250 kcrw.com##.actions 17track.net,5newsonline.com,6abc.com,7online.com,aa.co.za,aarp.org,abc11.com,abc13.com,abc30.com,abc7.com,abc7chicago.com,abc7news.com,abovethelaw.com,accringtonobserver.co.uk,adelaidenow.com.au,adn.com,adsoftheworld.com,adsupplyads.com,adtmag.com,adweek.com,aero-news.net,aetv.com,agra-net.net,ahlanlive.com,algemeiner.com,aljazeera.com,allkpop.com,allrecipes.co.in,allrecipes.com.au,amandala.com.bz,americanprofile.com,amny.com,anandtech.com,androidapps.com,androidauthority.com,aol.com,appolicious.com,arabianbusiness.com,arseniohall.com,articlealley.com,asianjournal.com,associationsnow.com,audiko.net,aussieoutages.com,autoblog.com,autoblog360.com,autoguide.com,aww.com.au,azarask.in,back9network.com,backlinkwatch.com,backtrack-linux.org,bathchronicle.co.uk,beaumontenterprise.com,bellinghamherald.com,bgr.com,bikesportnews.com,birminghammail.co.uk,birminghampost.co.uk,blackmorevale.co.uk,bloomberg.com,bloombergview.com,bnd.com,bobvila.com,boston.com,bostonglobe.com,bostontarget.co.uk,bradenton.com,bravotv.com,breitbart.com,brentwoodgazette.co.uk,bridesmagazine.co.uk,brisbanetimes.com.au,bristolpost.co.uk,budgettravel.com,burbankleader.com,businessinsider.com,businesstech.co.za,businessweek.com,c21media.net,cairnspost.com.au,canadianoutages.com,canberratimes.com.au,canterburytimes.co.uk,carmarthenjournal.co.uk,carynews.com,cd1025.com,celebdigs.com,celebified.com,centralsomersetgazette.co.uk,centredaily.com,cfl.ca,cfo.com,ch-aviation.com,channel5.com,charismamag.com,charismanews.com,charlotteobserver.com,cheddarvalleygazette.co.uk,cheezburger.com,chesterchronicle.co.uk,chicagobusiness.com,chicagomag.com,chinahush.com,chinasmack.com,christianexaminer.com,christianlifenews.com,chroniclelive.co.uk,cio.com,citeworld.com,citylab.com,citysearch.com,claytonnewsstar.com,clientmediaserver.com,cloudtime.to,cltv.com,cnet.com,cnn.com,coastlinepilot.com,codepen.io,collinsdictionary.com,colorlines.com,colourlovers.com,comcast.net,comicbookmovie.com,competitor.com,computerworld.com,cornishguardian.co.uk,cornishman.co.uk,courier.co.uk,couriermail.com.au,coventrytelegraph.net,cpuboss.com,crawleynews.co.uk,crewechronicle.co.uk,crossmap.com,crosswalk.com,croydonadvertiser.co.uk,csoonline.com,csswizardry.com,cupcakesandcashmere.com,cw33.com,cw39.com,cydiaupdates.net,dailycute.net,dailylobo.com,dailylocal.com,dailyparent.com,dailypilot.com,dailypost.co.uk,dailyrecord.co.uk,dailytarheel.com,dailytelegraph.com.au,dawn.com,dcw50.com,deadline.com,dealnews.com,defenseone.com,delish.com,derbytelegraph.co.uk,deseretnews.com,designtaxi.com,dinozap.com,divxstage.to,dodgeforum.com,domain.com.au,dorkingandleatherheadadvertiser.co.uk,dose.com,dover-express.co.uk,downdetector.co.nz,downdetector.co.uk,downdetector.co.za,downdetector.com,downdetector.in,downdetector.sg,dpreview.com,dribbble.com,drive.com.au,dustcoin.com,earmilk.com,earthsky.org,eastgrinsteadcourier.co.uk,eastlindseytarget.co.uk,edmontonjournal.com,elle.com,emedtv.com,engadget.com,enquirerherald.com,espnfc.co.uk,espnfc.com,espnfc.com.au,espnfc.us,espnfcasia.com,essentialbaby.com.au,essentialkids.com.au,essexchronicle.co.uk,eurocheapo.com,everyjoe.com,examiner.co.uk,examiner.com,excellence-mag.com,exeterexpressandecho.co.uk,expressnews.com,familydoctor.org,farmersguardian.com,farmonlinelivestock.com.au,fashionweekdaily.com,fastcar.co.uk,femalefirst.co.uk,fijitimes.com,findthatpdf.com,findthebest.co.uk,findthebest.com,flashx.tv,floridaindependent.com,fodors.com,folkestoneherald.co.uk,food.com,foodandwine.com,foodnetwork.com,fortmilltimes.com,fox13now.com,fox17online.com,fox2now.com,fox40.com,fox43.com,fox4kc.com,fox59.com,fox5sandiego.com,fox6now.com,fox8.com,foxafrica.com,foxbusiness.com,foxcrimeafrica.com,foxct.com,foxnews.com,foxsoccer.com,foxsportsasia.com,freedom43tv.com,freshpips.com,fresnobee.com,fromestandard.co.uk,fuse.tv,fxafrica.tv,fxnetworks.com,fxnowcanada.ca,gamefuse.com,gamemazing.com,garfield.com,gazettelive.co.uk,geelongadvertiser.com.au,getbucks.co.uk,getreading.co.uk,getsurrey.co.uk,getwestlondon.co.uk,givesmehope.com,glendalenewspress.com,glennbeck.com,gloucestercitizen.co.uk,gloucestershireecho.co.uk,go.com,gocomics.com,goerie.com,goldcoastbulletin.com.au,goo.im,good.is,goodfood.com.au,goodhousekeeping.com,gpuboss.com,grab.by,grapevine.is,greatschools.org,greenbot.com,grimsbytelegraph.co.uk,grindtv.com,grubstreet.com,gumtree.co.za,happytrips.com,hbindependent.com,healthyplace.com,heatworld.com,heraldonline.com,heraldsun.com.au,history.com,hknepaliradio.com,hodinkee.com,hollywood-elsewhere.com,hollywoodreporter.com,hoovers.com,houserepairtalk.com,houstonchronicle.com,hulldailymail.co.uk,idahostatesman.com,idganswers.com,independent.co.uk,indianas4.com,indiewire.com,indyposted.com,infoworld.com,inhabitat.com,instyle.com,interest.co.nz,interfacelift.com,interfax.com.ua,intoday.in,investopedia.com,investsmart.com.au,iono.fm,irishmirror.ie,irishoutages.com,islandpacket.com,itsamememario.com,itv.com,itworld.com,jackfm.ca,jamaica-gleaner.com,javaworld.com,jobs.com.au,journalgazette.net,joystiq.com,jsonline.com,juzupload.com,katc.com,kbzk.com,kdvr.com,kentucky.com,keysnet.com,kfor.com,kidspot.com.au,kiss959.com,koaa.com,kob.com,komando.com,koreabang.com,kotaku.com.au,kpax.com,kplr11.com,kqed.org,ktla.com,kusports.com,kwgn.com,kxlf.com,kxlh.com,lacanadaonline.com,lakewyliepilot.com,lawrence.com,leaderpost.com,ledger-enquirer.com,leicestermercury.co.uk,lex18.com,lichfieldmercury.co.uk,lincolnshireecho.co.uk,liverpoolecho.co.uk,ljworld.com,llanellistar.co.uk,lmtonline.com,lolbrary.com,loop21.com,lordofthememe.com,lostateminor.com,loughboroughecho.net,lsjournal.com,macclesfield-express.co.uk,macombdaily.com,macon.com,macrumors.com,manchestereveningnews.co.uk,mangafox.me,marieclaire.com,marketwatch.com,mashable.com,maxpreps.com,mcclatchydc.com,mediafire.com,memearcade.com,memeslanding.com,memestache.com,mercedsunstar.com,mercurynews.com,metronews.ca,miamiherald.com,middevongazette.co.uk,military.com,minecrastinate.com,mirror.co.uk,mkweb.co.uk,mlb.mlb.com,modbee.com,monkeysee.com,monroenews.com,montrealgazette.com,motorcycle.com,motorcycleroads.com,movies.com,movshare.net,mozo.com.au,mprnews.org,mrconservative.com,mrmovietimes.com,mrqe.com,msn.com,muchshare.net,mugglenet.com,mybroadband.co.za,mycareer.com.au,myfox8.com,mygaming.co.za,myhomeremedies.com,mylifeisaverage.com,mypaper.sg,myrtlebeachonline.com,mysearchresults.com,nation.co.ke,nation.com.pk,nationaljournal.com,nature.com,nbcsportsradio.com,networkworld.com,news.com.au,newsfixnow.com,newsobserver.com,newsok.com,newstimes.com,newtimes.co.rw,nextmovie.com,nhregister.com,nickmom.com,northdevonjournal.co.uk,notsafeforwallet.net,nottinghampost.com,novamov.com,nowvideo.co,nowvideo.li,nowvideo.sx,ntd.tv,ntnews.com.au,ny1.com,nymag.com,nytco.com,nytimes.com,offbeat.com,omgfacts.com,osadvertiser.co.uk,osnews.com,ottawamagazine.com,ovguide.com,patch.com,patheos.com,peakery.com,perthnow.com.au,phl17.com,photobucket.com,pingtest.net,pirateshore.org,pix11.com,plosone.org,plymouthherald.co.uk,pokestache.com,polygon.com,popsugar.com,popsugar.com.au,prepperwebsite.com,primeshare.tv,pv-tech.org,q13fox.com,quackit.com,quibblo.com,ragestache.com,ranker.com,readmetro.com,realestate.com.au,realityblurred.com,redeyechicago.com,redmondmag.com,refinery29.com,relish.com,retailgazette.co.uk,retfordtimes.co.uk,reuters.com,roadsideamerica.com,rogerebert.com,rollcall.com,rossendalefreepress.co.uk,rumorfix.com,runcornandwidnesweeklynews.co.uk,runnow.eu,sacbee.com,sadlovequotes.net,sanluisobispo.com,sbs.com.au,scpr.org,scubadiving.com,scunthorpetelegraph.co.uk,seattletimes.com,sevenoakschronicle.co.uk,sfchronicle.com,sfgate.com,sfx.co.uk,sheptonmalletjournal.co.uk,shtfplan.com,si.com,similarsites.com,simpledesktops.com,singingnews.com,sixbillionsecrets.com,sky.com,slacker.com,slate.com,sleafordtarget.co.uk,slidetoplay.com,smackjuice.com,smartcompany.com.au,smartphowned.com,smh.com.au,softpedia.com,somersetguardian.co.uk,southportvisiter.co.uk,southwales-eveningpost.co.uk,spectator.org,spin.com,spokesman.com,sportsdirectinc.com,springwise.com,spryliving.com,ssdboss.com,ssireview.org,stagevu.com,stamfordadvocate.com,standard.co.uk,star-telegram.com,statenews.com,statscrop.com,stltoday.com,stocktwits.com,stokesentinel.co.uk,stoppress.co.nz,streetinsider.com,stripes.com,stroudlife.co.uk,stv.tv,sub-titles.net,sunherald.com,surfline.com,surreymirror.co.uk,suttoncoldfieldobserver.co.uk,talkandroid.com,tampabay.com,tamworthherald.co.uk,tasteofawesome.com,teamcoco.com,techdirt.com,tgdaily.com,thanetgazette.co.uk,thatslife.com.au,thatssotrue.com,theage.com.au,theatlantic.com,theaustralian.com.au,theblaze.com,thedailybeast.com,thedp.com,theepochtimes.com,thefirearmblog.com,thefreedictionary.com,thegamechicago.com,thegossipblog.com,thegrio.com,thegrocer.co.uk,thehungermemes.net,thejournal.co.uk,thekit.ca,themercury.com.au,thenation.com,thenewstribune.com,theoaklandpress.com,theolympian.com,theonion.com,theprovince.com,therealdeal.com,theroot.com,thesaurus.com,thestack.com,thestarphoenix.com,thestate.com,thevine.com.au,thewalkingmemes.com,thewindowsclub.com,thewire.com,thisiswhyimbroke.com,time.com,timeshighereducation.co.uk,timesunion.com,tinypic.com,today.com,tokyohive.com,topsite.com,torontoist.com,torquayheraldexpress.co.uk,touringcartimes.com,townandcountrymag.com,townsvillebulletin.com.au,travelocity.com,travelweekly.com,tri-cityherald.com,tribecafilm.com,tripadvisor.ca,tripadvisor.co.uk,tripadvisor.co.za,tripadvisor.com,tripadvisor.ie,tripadvisor.in,triplem.com.au,trucktrend.com,truecar.com,tv3.ie,twcc.com,twcnews.com,ufc.com,uinterview.com,unfriendable.com,userstyles.org,usnews.com,vancouversun.com,veevr.com,vetfran.com,vg247.com,vid.gg,vidbux.com,videobash.com,videoweed.es,vidxden.com,vidxden.to,viralnova.com,vogue.com.au,vulture.com,walesonline.co.uk,walsalladvertiser.co.uk,washingtonpost.com,watchanimes.me,watoday.com.au,wattpad.com,watzatsong.com,way2sms.com,wbur.org,weathernationtv.com,webdesignerwall.com,webestools.com,weeklytimesnow.com.au,wegotthiscovered.com,wellcommons.com,wellsjournal.co.uk,westbriton.co.uk,westerndailypress.co.uk,westerngazette.co.uk,westernmorningnews.co.uk,wetpaint.com,wgno.com,wgnradio.com,wgnt.com,wgntv.com,whnt.com,whosay.com,whotv.com,wildcat.arizona.edu,windsorstar.com,winewizard.co.za,wnep.com,womansday.com,worldreview.info,worthplaying.com,wow247.co.uk,wqad.com,wral.com,wreg.com,wrestlezone.com,wsj.com,wtkr.com,wtvr.com,www.google.com,x17online.com,yahoo.com,yonhapnews.co.kr,yorkpress.co.uk,yourmiddleeast.com,zedge.net,zillow.com,zooweekly.com.au,zybez.net##.ad yahoo.com##.ad-active deviantart.com##.ad-blocking-makes-fella-confused alarabiya.net,edmunds.com,flightaware.com,haaretz.com,journalism.co.uk,memecdn.com,memecenter.com,metrolyrics.com,pcworld.in,reverso.net,revision3.com,soapoperadigest.com,tasteofhome.com,twitpic.com,vinesbay.com,viralnova.com,where.ca##.ad-box 9news.com.au,beautifuldecay.com,boston.com,businessinsider.com.au,cpuboss.com,dnainfo.com,downforeveryoneorjustme.com,engineeringnews.co.za,firehouse.com,glamour.com,gpuboss.com,ign.com,isup.me,komando.com,macstories.net,moneysense.ca,nbcnews.com,refinery29.com,rollingstone.com,slate.com,sltrib.com,ssdboss.com,stockhouse.com,theaustralian.com.au,themercury.com.au,thrillist.com,youtube.com##.ad-container wusa9.com##.ad-image hollywoodjournal.com##.ad-title vesselfinder.com##.ad0 bnqt.com##.ad05 afreecodec.com,brothersoft.com,gamrreview.com,indiatimes.com,msn.com,rodalenews.com,sundaymail.co.zw,sundaynews.co.zw,webmaster-source.com##.ad1 brothersoft.com,livemint.com,nowvideo.co,nowvideo.eu,nowvideo.li,nowvideo.sx,roms4droid.com,sundaymail.co.zw,sundaynews.co.zw##.ad2 afreecodec.com,livemint.com,mpog100.com,sundaymail.co.zw,sundaynews.co.zw##.ad3 hitfreegames.com,sundaymail.co.zw,sundaynews.co.zw##.ad4 sundaymail.co.zw,sundaynews.co.zw,vesselfinder.com##.ad5 sundaymail.co.zw,sundaynews.co.zw##.ad6 sundaymail.co.zw,sundaynews.co.zw##.ad7 ngrguardiannews.com##.ad9 buy.com##.adBG browardpalmbeach.com,cafemom.com,chacha.com,cio.co.uk,citypages.com,computerworlduk.com,cvs.com,dallasobserver.com,digitalartsonline.co.uk,flightradar24.com,geek.com,globaltv.com,houstonpress.com,laweekly.com,macworld.co.uk,miaminewtimes.com,newspakistan.pk,nytimes.com,ocweekly.com,pcadvisor.co.uk,petagadget.com,phoenixnewtimes.com,reuters.com,riverfronttimes.com,sfweekly.com,sky.com,t3.com,thehimalayantimes.com,villagevoice.com,westword.com,yakimaherald.com##.adContainer webfail.com##.adMR ifaonline.co.uk,relink.us##.ad_right telegraph.co.uk##.adarea + .summaryMedium englishrussia.com,keepvid.com,metrowestdailynews.com##.adb pencurimovie.cc##.adb_overlay aol.com,beautysouthafrica.com,blurtit.com,breakingnews.com,digitalhome.ca,eurowerks.org,heyuguys.co.uk,longislandpress.com,opensourcecms.com,opposingviews.com,readersdigest.co.uk,songlyrics.com,sugarrae.com,techeblog.com,thebizzare.com##.adblock orbitztv.co.uk##.adblockcreatorssuckmydick affiliatefix.com,blogto.com,capitalfm.com.my,cargoinfo.co.za,lockerz.com,macdailynews.com,mensjournal.com,midnightpoutine.ca,mvnrepository.com,ow.ly,podfeed.net,pricespy.co.nz,sfbayview.com,viralnova.com,whatsmyip.org,willyweather.com.au##.adbox webtoolhub.com##.adbx search.ch##.adcell msn.com##.adcicon fanatix.com,nfl.com,theconstructionindex.co.uk##.adcontainer runnerspace.com##.adcontent allrovi.com,bdnews24.com,hotnewhiphop.com,itproportal.com,nciku.com,newvision.co.ug,yourepeat.com##.add africareview.com##.add-banner 1049.fm,drgnews.com##.add-box addictivetips.com##.add-under-post time4tv.com##.add1 sundownsfc.co.za##.add2 forexminute.com##.add4 tvnz.co.nz##.addHolder investorschronicle.co.uk##.addPlacement worldissues360.com##.addWrapper ibnlive.in.com##.add_box yellowpages.ae##.add_main_div inspiyr.com##.add_unit inspiyr.com##.add_unit1 yellowpages.ae##.add_view300_250 gbcghana.com##.addbg hscripts.com##.addbox funmunch.com##.addimage cadenaazul.com,ibnlive.in.com,intoday.in,lapoderosa.com,telegraph.co.uk##.adds oyefm.in##.addv techhamlet.com##.adhered naldzgraphics.net##.adis thedailystar.net##.adivvert usabit.com##.adk2_slider_baner pbs.org##.adl animalfactguide.com,ask.com,bigislandnow.com,dnainfo.com,globalpost.com,portlandmonthlymag.com##.adlabel ebookbrowse.com##.adleft vietnamnet.vn##.adm_c1 ncaa.com##.adman-label jokeroo.com##.admb experienceproject.com##.adn flightglobal.com##.adp bodyboardingmovies.com##.adpopup bodyboardingmovies.com##.adpopup-overlay iamwire.com##.adr iskullgames.com##.adr300 zercustoms.com##.adrh 1sale.com,7billionworld.com,abajournal.com,altavista.com,androidfilehost.com,arcadeprehacks.com,asbarez.com,birdforum.net,coinad.com,cuzoogle.com,cyclingweekly.co.uk,disconnect.me,domainnamenews.com,eco-business.com,energylivenews.com,facemoods.com,fcall.in,flashx.tv,foxbusiness.com,foxnews.com,freetvall.com,friendster.com,fstoppers.com,ftadviser.com,furaffinity.net,gentoo.org,gmanetwork.com,govtrack.us,gramfeed.com,gyazo.com,hispanicbusiness.com,html5test.com,hurricanevanessa.com,i-dressup.com,iheart.com,ilovetypography.com,irennews.org,isearch.whitesmoke.com,itar-tass.com,itproportal.com,kingdomrush.net,laptopmag.com,laweekly.com,lfpress.com,livetvcafe.net,lovemyanime.net,malaysiakini.com,manga-download.org,maps.google.com,marinetraffic.com,mb.com.ph,meaningtattos.tk,mmajunkie.com,movies-online-free.net,mugshots.com,myfitnesspal.com,mypaper.sg,nbcnews.com,news.nom.co,nsfwyoutube.com,nugget.ca,osn.com,panorama.am,pastie.org,phpbb.com,playboy.com,pocket-lint.com,pokernews.com,previously.tv,radiobroadcaster.org,reason.com,ryanseacrest.com,savevideo.me,sddt.com,searchfunmoods.com,sgcarmart.com,shopbot.ca,sourceforge.net,tcm.com,tech2.com,thecambodiaherald.com,thedailyobserver.ca,thejakartapost.com,thelakewoodscoop.com,themalaysianinsider.com,theobserver.ca,thepeterboroughexaminer.com,theyeshivaworld.com,tiberium-alliances.com,tjpnews.com,today.com,tubeserv.com,turner.com,twogag.com,ultimate-guitar.com,wallpaper.com,washingtonpost.com,wdet.org,wftlsports.com,womanandhome.com,wtvz.net,yahoo.com,youthedesigner.com,yuku.com##.ads glarysoft.com##.ads + .search-list searchfunmoods.com##.ads + ul > li y8.com##.ads-bottom-table .grey-box-bg playboy.com##.ads-column > h2 girlgames4u.com,xing.com##.ads-container extratorrent.cc,hitfreegames.com,movies-online-free.net,twogag.com##.ads2 twogag.com##.ads5 twogag.com##.adsPW twogag.com##.adsPW2 localmoxie.com##.ads_tilte localmoxie.com##.ads_tilte + .main_mid_ads entrepreneur.com##.adsby bloomberg.com,borfast.com,howmanyleft.co.uk,instantpulp.com,mysmartprice.com,nintandbox.net,nycity.today,over-blog.com,plurk.com,scitechdaily.com,sgentrepreneurs.com,techsupportalert.com,wikihoops.com,wlds.com##.adsense ravchat.com##.adsh search.b1.org##.adslabel animeid.com##.adspl desertdispatch.com,geeky-gadgets.com,highdesert.com,journalgazette.net,lgbtqnation.com,miamitodaynews.com,myrecipes.com,search.certified-toolbar.com,thevoicebw.com,vvdailypress.com,wsj.com##.adtext reason.com,rushlimbaugh.com##.adtitle ansamed.info,baltic-course.com,carsdirect.com,cbc.ca,cineuropa.org,cpuid.com,facebook.com,flicks.co.nz,futbol24.com,gametrailers.com,getwapi.com,howstuffworks.com,intoday.in,isearch.omiga-plus.com,massappeal.com,mnn.com,mtv.com,mysuncoast.com,ok.co.uk,ponged.com,prohaircut.com,qone8.com,roadfly.com,rockol.com,rumorcontrol.info,runamux.net,search.v9.com,ultimate-guitar.com,vh1.com,webssearches.com,xda-developers.com,zbani.com##.adv luxury-insider.com##.adv-info veoh.com##.adv-title btn.com##.adv-widget animefushigi.com##.adv1 futbol24.com##.adv2 prohaircut.com##.adv3 yesasia.com##.advHr gametrailers.com,themoscowtimes.com##.adv_block vietnamnet.vn##.adv_info dt-updates.com##.adv_items faceyourmanga.com##.adv_special infoplease.com##.advb 98online.com,adballa.com,allghananews.com,arabianindustry.com,bitcoinzebra.com,bloomberg.com,cbc.ca,chemicalwatch.com,craveonline.com,dawn.com,designmena.com,express.co.uk,expressandstar.com,farmprogress.com,foxbusiness.com,foxnews.com,gfi.com,guernseypress.com,gulfnews.com,healthcanal.com,healthguru.com,healthinsurancedaily.com,hollywoodreporter.com,hoteliermiddleeast.com,humanipo.com,huntspost.co.uk,jerseyeveningpost.com,journeychristiannews.com,kumusika.co.zw,legendarypokemon.net,mmegi.bw,morningstar.co.uk,msnbc.com,myfinances.co.uk,ninemsn.com.au,outdoorchannel.com,phnompenhpost.com,piccsy.com,shropshirestar.com,skysports.com,sowetanlive.co.za,sundayworld.co.za,technewstoday.com,tenplay.com.au,thecomet.net,thegayuk.com,thejournal.ie,thetribunepapers.com,totalscifionline.com,travelchannel.com,trucksplanet.com,tvweek.com,vg247.com,winewizard.co.za,wow247.co.uk,xfire.com##.advert naldzgraphics.net##.advertBSA bandwidthblog.com,demerarawaves.com,eaglecars.com,earth911.com,pcmag.com,proporn.com,slodive.com,smartearningsecrets.com,smashingapps.com,theawesomer.com,thepeninsulaqatar.com##.advertise thepeninsulaqatar.com##.advertise-09 dailyvoice.com##.advertise-with-us citysearch.com##.advertiseLink insiderpages.com##.advertise_with_us 1520wbzw.com,760kgu.biz,880thebiz.com,about.com,afro.com,allmusic.com,amctv.com,animax-asia.com,ap.org,araratadvertiser.com.au,areanews.com.au,armidaleexpress.com.au,avclub.com,avonadvocate.com.au,axn-asia.com,barossaherald.com.au,batemansbaypost.com.au,baysidebulletin.com.au,begadistrictnews.com.au,bellingencourier.com.au,bendigoadvertiser.com.au,betvasia.com,bigthink.com,biz1190.com,bizarremag.com,blacktownsun.com.au,blayneychronicle.com.au,bluemountainsgazette.com.au,boingboing.net,bombalatimes.com.au,boorowanewsonline.com.au,bordermail.com.au,braidwoodtimes.com.au,bravotv.com,brimbankweekly.com.au,bunburymail.com.au,business1110ktek.com,business1570.com,businessinsurance.com,busseltonmail.com.au,camdenadvertiser.com.au,camdencourier.com.au,canowindranews.com.au,caranddriver.com,carrierethernetnews.com,caseyweekly.com.au,caseyweeklycranbourne.com.au,centraladvocate.com.au,centralwesterndaily.com.au,cessnockadvertiser.com.au,cinemablend.com,classicandperformancecar.com,clickhole.com,colliemail.com.au,colypointobserver.com.au,competitor.com,coomaexpress.com.au,cootamundraherald.com.au,cowraguardian.com.au,crainsnewyork.com,crookwellgazette.com.au,crosswalk.com,dailyadvertiser.com.au,dailygazette.com,dailyliberal.com.au,dailyrecord.com,dandenongjournal.com.au,defenceweb.co.za,di.fm,donnybrookmail.com.au,downloadcrew.com,dunedintv.co.nz,dungogchronicle.com.au,easternriverinachronicle.com.au,edenmagnet.com.au,elliottmidnews.com.au,esperanceexpress.com.au,essentialmums.co.nz,examiner.com.au,eyretribune.com.au,fairfieldchampion.com.au,fastcocreate.com,fastcodesign.com,financialcontent.com,finnbay.com,forbesadvocate.com.au,frankstonweekly.com.au,gazettextra.com,gematsu.com,gemtvasia.com,gippslandtimes.com.au,gleninnesexaminer.com.au,globest.com,gloucesteradvocate.com.au,goodcast.org,goondiwindiargus.com.au,goulburnpost.com.au,greatlakesadvocate.com.au,grenfellrecord.com.au,guyraargus.com.au,hardenexpress.com.au,hawkesburygazette.com.au,hepburnadvocate.com.au,hillsnews.com.au,hispanicbusiness.com,humeweekly.com.au,huntervalleynews.net.au,i-dressup.com,imgur.com,inverelltimes.com.au,irishtimes.com,juneesoutherncross.com.au,kansas.com,katherinetimes.com.au,kdow.biz,kkol.com,knoxweekly.com.au,lakesmail.com.au,lamag.com,latrobevalleyexpress.com.au,legion.org,lithgowmercury.com.au,liverpoolchampion.com.au,livestrong.com,livetennis.com,macarthuradvertiser.com.au,macedonrangesweekly.com.au,macleayargus.com.au,magtheweekly.com,mailtimes.com.au,maitlandmercury.com.au,mandurahmail.com.au,manningrivertimes.com.au,margaretrivermail.com.au,maribyrnongweekly.com.au,marinmagazine.com,marketwatch.com,maroondahweekly.com.au,meltonweekly.com.au,merimbulanewsonline.com.au,merredinmercury.com.au,metservice.com,monashweekly.com.au,money1055.com,mooneevalleyweekly.com.au,moreechampion.com.au,movies4men.co.uk,mprnews.org,msn.com,mudgeeguardian.com.au,murrayvalleystandard.com.au,muswellbrookchronicle.com.au,myallcoastnota.com.au,nambuccaguardian.com.au,naroomanewsonline.com.au,narrominenewsonline.com.au,nationalgeographic.com,newcastlestar.com.au,northernargus.com.au,northerndailyleader.com.au,northweststar.com.au,nvi.com.au,nynganobserver.com.au,nytimes.com,oann.com,oberonreview.com.au,onetvasia.com,onlinegardenroute.co.za,orange.co.uk,parenthood.com,parkeschampionpost.com.au,parramattasun.com.au,pch.com,peninsulaweekly.com.au,penrithstar.com.au,plasticsnews.com,portlincolntimes.com.au,portnews.com.au,portpirierecorder.com.au,portstephensexaminer.com.au,praguepost.com,psychologytoday.com,queanbeyanage.com.au,racingbase.com,radioguide.fm,redsharknews.com,rhsgnews.com.au,riverinaleader.com.au,roxbydownssun.com.au,rubbernews.com,saitnews.co.za,sconeadvocate.com.au,silverdoctors.com,singletonargus.com.au,smallbusiness.co.uk,sonychannel.co.za,sonychannelasia.com,sonymax.co.za,sonymoviechannel.co.uk,sonytv.com,southcoastregister.com.au,southernhighlandnews.com.au,southernweekly.com.au,southwestadvertiser.com.au,standard.net.au,star-telegram.com,stawelltimes.com.au,stmarysstar.com.au,stonningtonreviewlocal.com.au,summitsun.com.au,suncitynews.com.au,sunjournal.com,sunraysiadaily.com.au,tennantcreektimes.com.au,tenterfieldstar.com.au,theadvocate.com,theadvocate.com.au,thebeachchannel.tv,thecourier.com.au,thecurrent.org,theflindersnews.com.au,theforecaster.net,theguardian.com.au,theherald.com.au,theislanderonline.com.au,theleader.com.au,thenortherntimes.com.au,theridgenews.com.au,therural.com.au,tirebusiness.com,townandcountrymagazine.com.au,transcontinental.com.au,travelpulse.com,twitch.tv,ulladullatimes.com.au,vanityfair.com,victorharbortimes.com.au,waginargus.com.au,walchanewsonline.com.au,walworthcountytoday.com,washingtonexaminer.com,wauchopegazette.com.au,wellingtontimes.com.au,westcoastsentinel.com.au,westernadvocate.com.au,westernmagazine.com.au,whyallanewsonline.com.au,winghamchronicle.com.au,wollondillyadvertiser.com.au,woot.com,wsj.com,wyndhamweekly.com.au,yasstribune.com.au,yellowpages.ca,youngwitness.com.au##.advertisement fieldandstream.com##.advertisement-fishing-contest 4v4.com,bn0.com,culttt.com,flicks.co.nz,shieldarcade.com,thethingswesay.com,who.is##.advertisements afr.com,afrsmartinvestor.com.au,afternoondc.in,allmusic.com,brw.com.au,chicagobusiness.com,cio.co.ke,filesoup.com,ft.com,glamour.co.za,gq.co.za,hellomagazine.com,kat.ph,kickass.so,kickass.to,kickassunblock.info,newsweek.com,ocregister.com,orangecounty.com,premier.org.uk,premierchildrenswork.com,premierchristianity.com,premierchristianradio.com,premiergospel.org.uk,premieryouthwork.com,radio.com,softarchive.net,theadvocate.com,tvnz.co.nz##.advertising katproxy.com,kickass.so,kickasstor.net,kickassunblock.info,kickassunblock.net##.advertising + .tabs mediatel.co.uk##.advertising_label ketknbc.com,ktsm.com##.advertisments computerworld.co.nz##.advertorial_title theglobeandmail.com##.advetorial file-extensions.org##.advicon javascript-coder.com##.advimg 148apps.com##.advnote mumsnet.com##.advo_box itweb.co.za,mani-admin-plugin.com##.advs search.chatzum.com##.adw voxxi.com##.adwidget instructables.com,mapquest.com,northjersey.com,npr.org,people.com,thestarphoenix.com##.adwrapper statistiks.co.uk,statistiks.com##.adz thumbtribe.mobi##.adzoneOldMutualWithoutHeading mail.google.com##.aeF .nH[role="main"] > .mq:last-child mail.google.com##.aeF > .nH > .nH[role="main"] > .aKB mail.google.com##.aeF > .nH > .nH[role="main"] > .afn:first-child + .mq mail.google.com##.aeF > .nH > .nH[role="main"] > .mq:first-child mail.google.com##.aeF > .nH > .nH[role="main"] > .nH > .nH > .AT[style] mail.google.com##.aeF > .nH > .nH[role="main"] > .nH > .nH > .nH > .mq:last-child mail.google.com##.aeF > .nH > .nH[role="main"] > div + .mq redown.se##.af toptut.com##.af-form adventuregamers.com##.af_disclaimer eurogamer.net##.affiliate deborah-bickel.de##.affiliate-werbe125 coolest-gadgets.com,cutezee.com,sen.com.au##.affiliates americasautosite.com##.affiliatesDiv cutezee.com##.affiliates_fp dailymotion.com##.affiliation_cont bplans.com##.affixed-sidebar-m digmyweb.com##.affsearch-container digmyweb.com##.affsearch-container-right surfwap.com,twilightwap.com##.ahblock2 world-airport-codes.com##.airport-affiliate allkpop.com##.akp_newslist_300x250 autos.msn.com##.al inquirer.net##.al-bb-box inquirer.net##.al-elb-frame ebay.com##.al32 300mbmovies4u.com,javascript-coder.com,media1fire.com,megashare.com##.alert kcsoftwares.com##.alert-success hbwm.com##.alignRight[style="margin-right:30px;color:#858585;"] empowernetwork.com##.align[bgcolor="#FCFA85"] searchizz.com##.also_block speedtest.net##.alt-promo-container > ul > .alt-promo:first-child + .alt-promo digitalhome.ca##.alt1[colspan="5"][style="border: 1px solid #ADADAD; background-image: none"] > div[align="center"] > .vdb_player techsupportforum.com##.alt1[style="border: 1px solid #ADADAD; background-image: none"] styleite.com##.am-ngg-right-ad colorhexa.com##.amain air1.com,imdb.com,nprstations.org,reviewed.com,squidoo.com,three.fm##.amazon imdb.com##.amazon-instant-video blogcritics.org##.amazon-item brickset.com##.amazonAd squidoo.com##.amazon_spotlight kuhf.org##.amazonaff herplaces.com##.amazonlink four11.com##.amed seventeen.com##.ams_bottom kingdomrush.net##.angry folowpeople.info##.anivia_add_space 4shared.com##.antivirusBanner 1337x.org##.anynomousDw directupload.net,pv-magazine.com##.anzeige directupload.net##.anzeiger mmorpg.com##.apante publicradio.org##.apm_playlist_item_affiliate publicradio.org##.apm_playlist_item_purchase_link cultofmac.com##.appDetailPanel-ad channelchooser.com##.append-bottom.last liveonlineradio.net##.art-Header2 skysports.com##.art-betlink carsession.com##.artBanner300 ibtimes.com##.art_content sigsiu.net##.artbannersplus pocket-lint.com##.article + .block selfgrowth.com##.article-banner jpost.com##.article-bottom-banner scoop.co.nz##.article-left-box trendhunter.com##.articleBox smh.com.au##.articleExtras-wrap shoppinglifestyle.com##.articleLREC telegraph.co.uk##.articleSponsor sosuanews.com##.article[style="width: 440px; background-color: #000066; margin: 6px; margin-top: 6px;"] iafrica.com##.article_Banner nzgamer.com##.article_banner_holder alternet.org##.article_insert_container app.com,argusleader.com,battlecreekenquirer.com,baxterbulletin.com,bucyrustelegraphforum.com,burlingtonfreepress.com,centralohio.com,chillicothegazette.com,cincinnati.com,citizen-times.com,clarionledger.com,coloradoan.com,coshoctontribune.com,courier-journal.com,courierpostonline.com,dailyrecord.com,dailyworld.com,delawareonline.com,delmarvanow.com,democratandchronicle.com,desmoinesregister.com,dnj.com,fdlreporter.com,freep.com,greatfallstribune.com,greenbaypressgazette.com,greenvilleonline.com,guampdn.com,hattiesburgamerican.com,hometownlife.com,honoluluadvertiser.com,htrnews.com,indystar.com,jacksonsun.com,jconline.com,lancastereaglegazette.com,lansingstatejournal.com,livingstondaily.com,lohud.com,mansfieldnewsjournal.com,marionstar.com,marshfieldnewsherald.com,montgomeryadvertiser.com,mycentraljersey.com,mydesert.com,newarkadvocate.com,news-leader.com,news-press.com,newsleader.com,pal-item.com,pnj.com,portclintonnewsherald.com,postcrescent.com,poughkeepsiejournal.com,press-citizen.com,pressconnects.com,rgj.com,sctimes.com,sheboyganpress.com,shreveporttimes.com,stargazette.com,statesmanjournal.com,stevenspointjournal.com,tallahassee.com,tennessean.com,theadvertiser.com,thecalifornian.com,thedailyjournal.com,theithacajournal.com,theleafchronicle.com,thenews-messenger.com,thenewsstar.com,thenorthwestern.com,thespectrum.com,thestarpress.com,thetimesherald.com,thetowntalk.com,visaliatimesdelta.com,wausaudailyherald.com,wisconsinrapidstribune.com,zanesvilletimesrecorder.com##.articleflex-container webpronews.com##.articleleftcol entrepreneur.com##.articlepromo burbankleader.com,citypaper.com,dailypilot.com,glendalenewspress.com,hbindependent.com,lacanadaonline.com,redeyechicago.com,vacationstarter.com,vagazette.com##.articlerail audiko.net##.artist-banner-right audiko.net##.artist-banner-right-cap eastrolog.com##.as300x250 moneycontrol.com##.asSponser memepix.com##.asblock xmodulo.com##.asdf-banner-zone four11.com##.asmall_l four11.com##.asmall_r instructables.com##.aspace freeads.co.uk##.ass_ad javascriptsource.com##.asset-section yahoo.com##.astro-promo ohioautofinder.com##.atLeaderboard ohioautofinder.com##.atMiniBanner herald.co.zw##.atbanners milesplit.com##.atf tvtropes.org##.atf_banner gamepedia.com,minecraftwiki.net##.atflb myshopping.com.au##.atip filedir.com##.atit pogdesign.co.uk##.atop webmd.com##.attrib_right_fmt webmd.com##.attribution majorgeeks.com##.author:first-child mail.yahoo.com##.avLogo ngrguardiannews.com##.avd_display_block receivesmsonline.net##.aviso gameplanet.co.nz##.avt-mr gameplanet.co.nz##.avt-placement m.facebook.com,touch.facebook.com##.aymlCoverFlow m.facebook.com,touch.facebook.com##.aymlNewCoverFlow[data-ft*="\"is_sponsored\":\"1\""] knowyourmeme.com##.aztc techspot.com##.azureDiv livejournal.com##.b-adv silvertorrent.org##.b-content[align="center"] > table[width="99%"] easyvectors.com##.b-footer alawar.com##.b-game-play__bnnr theartnewspaper.com##.b-header-banners sammobile.com##.b-placeholder bizcommunity.com##.b-topbanner flvto.com##.b1 scorespro.com##.b160_600 flv2mp3.com,flvto.com##.b2 flv2mp3.com##.b3 scorespro.com##.b300 impactwrestling.com,jumptogames.com,tnawrestling.com##.b300x250 itproportal.com##.b4nn3r scorespro.com##.b60 gazeta.kz##.bBanner connectamarillo.com,northwestohio.com##.bI-page-lead-upper flv2mp3.com,flvto.com##.b_phone autotrader.ca##.ba1 autotrader.ca##.ba2 autotrader.ca##.ba3 hellomagazine.com##.backBanner xfire.com##.background modders-inc.com,thessdreview.com,thestar.ie##.background-cover broadway.com,treehousetv.com##.badge garfield.com##.badgeBackground downbyte.net##.badw pravda.ru##.ban-center india.com##.ban-rgt-cng-ab xbox360cheats.com##.ban160 evilmilk.com,xbox360cheats.com##.ban300 worldstarhiphop.com##.banBG worldstarhiphop.com##.banOneCon kiz10.com##.ban_300_250 stream2watch.com##.ban_b izismile.com##.ban_top america.fm##.banbo webscribble.com##.baner hypemixtapes.com##.baner600 f-picture.net##.banerBottom sxc.hu##.bann 4music.com,90min.com,964eagle.co.uk,adage.com,ameinfo.com,angryduck.com,anyclip.com,aol.com,arcadebomb.com,b-metro.co.zw,bayt.com,betterrecipes.com,bikechatforums.com,billboard.com,blackamericaweb.com,bored-bored.com,boxoffice.com,bukisa.com,cadplace.co.uk,cineuropa.org,cmo.com.au,cnn.com,cnnmobile.com,coryarcangel.com,dreamteamfc.com,echoroukonline.com,ecorporateoffices.com,elyricsworld.com,entrepreneur.com,euobserver.com,eurochannel.com,everyday.com.kh,evilmilk.com,fantasyleague.com,fieldandstream.com,filenewz.com,footballtradedirectory.com,forexpeacearmy.com,forum.dstv.com,freshbusinessthinking.com,freshtechweb.com,funpic.hu,gamebanshee.com,gamehouse.com,gamersbook.com,garfield.com,gatewaynews.co.za,gd.tuwien.ac.at,general-catalog.com,general-files.com,general-video.net,generalfil.es,ghananation.com,girlsocool.com,globaltimes.cn,gsprating.com,healthsquare.com,hitfreegames.com,hotfrog.ca,hotfrog.co.nz,hotfrog.co.uk,hotfrog.co.za,hotfrog.com,hotfrog.com.au,hotfrog.com.my,hotfrog.ie,hotfrog.in,hotfrog.ph,hotfrog.sg,hotnewhiphop.com,howard.tv,htxt.co.za,humanipo.com,hyipexplorer.com,ibtimes.co.in,ibtimes.co.uk,iconfinder.com,iguide.to,imedicalapps.com,imnotobsessed.com,insidefutbol.com,internationalmeetingsreview.com,internetnews.com,irishtimes.com,isohunt.to,isource.com,itreviews.com,japantimes.co.jp,jewishtimes.com,keepcalm-o-matic.co.uk,ketknbc.com,kicknews.com,kijiji.ca,ktsm.com,leo.org,livescore.in,lmgtfy.com,locatetv.com,londonstockexchange.com,looklocal.co.za,manolith.com,mariopiperni.com,mmosite.com,motherboard.tv,motortrend.com,moviezadda.com,mzhiphop.com,naij.com,nehandaradio.com,netmums.com,networkworld.com,nuttymp3.com,oceanup.com,pdfmyurl.com,postzambia.com,premierleague.com,priceviewer.com,proxyhttp.net,ptotoday.com,rapidlibrary.com,reference.com,reversephonesearch.com.au,semiaccurate.com,smartcarfinder.com,snakkle.com,soccer24.co.zw,sportsvibe.co.uk,sumodb.com,sweeting.org,tennis.com,thebull.com.au,thefanhub.com,thefringepodcast.com,thehill.com,thehun.com,thesaurus.com,theskinnywebsite.com,time4tv.com,timeslive.co.za,tmi.me,torrent.cd,travelpulse.com,trutv.com,tvsquad.com,twirlit.com,umbrelladetective.com,universalmusic.com,ustream.tv,vice.com,viralnova.com,weather.gc.ca,weatheronline.co.uk,wego.com,whatsock.com,worldcrunch.com,xda-developers.com,yellowbook.com,yellowpages.com.jo,zbigz.com##.banner autotrader.co.uk##.banner--7th-position autotrader.co.uk##.banner--leaderboard autotrader.co.uk##.banner--skyscraper ariacharts.com.au,nation.sc,techshout.com##.banner-1 nation.sc##.banner-2 foodingredientsfirst.com,nutritionhorizon.com##.banner-250 nation.sc##.banner-3 nbcsports.com,onrpg.com,usahealthcareguide.com##.banner-300-250 alltop.com##.banner-background luxgallery.com##.banner-big-cotent yellowpages.com.lb##.banner-box 1027dabomb.net##.banner-btf softonic.com##.banner-caption farmonline.com.au,farmweekly.com.au,goodfruitandvegetables.com.au,jewsnews.co.il,knowledgerush.com,narutoforums.com,northqueenslandregister.com.au,privatehealth.co.uk,queenslandcountrylife.com.au,stockandland.com.au,stockjournal.com.au,student-jobs.co.uk,teenspot.com,theland.com.au,turfcraft.com.au,vh1.com##.banner-container privatehealth.co.uk##.banner-container-center soccerway.com##.banner-content moviesplanet.com##.banner-des dealchecker.co.uk##.banner-header medicalxpress.com,phys.org,pixdaus.com,reference.com,tennis.com,thesaurus.com##.banner-holder freecode.com##.banner-imu neowin.net##.banner-leaderboard savevid.com##.banner-main-198x300 audiko.net,extremesportman.com,ganool.com##.banner-right extremesportman.com##.banner-right-two humorsharing.com##.banner-side freecode.com##.banner-sky spin.com##.banner-slot neogamr.net,neowin.net##.banner-square intomobile.com##.banner-tbd audiko.net,carpartswholesale.com,greatbritishlife.co.uk,nationmultimedia.com,pwinsider.com,rapdose.com,usahealthcareguide.com,wired.co.uk,xda-developers.com##.banner-top feedmyapp.com##.banner-wrap general-catalog.com##.banner-wrap-hor manualslib.com,thenextweb.com,ustream.tv##.banner-wrapper isohunt.to##.banner-wrp ctv.ca##.banner01-holder ctv.ca##.banner02 thinkdigit.com##.banner03 coolest-gadgets.com,depositfiles.com,dfiles.eu,freecode.com,israeldefense.com,popcrunch.com,priceviewer.com,thelakewoodscoop.com,usa-people-search.com,wired.co.uk##.banner1 angryduck.com##.banner160-title azernews.az##.banner1_1 flixflux.co.uk,gsprating.com,jamieoliver.com,thelakewoodscoop.com,usa-people-search.com##.banner2 blogtv.com##.banner250 motorcycle-usa.com##.banner300x100 motorcycle-usa.com##.banner300x250 celebuzz.com,pinkisthenewblog.com##.banner728-wrapper mixfmradio.com##.banner728_border cambodiayp.com,nepalyp.com##.banner750 christianpost.com##.bannerBottom britsabroad.com,diymobileaudio.com,hotfilms.org,itechtalk.com,legendarydevils.com,mechodownload.com,thegamingsource.co,yummy.ph,zeetvusa.com##.bannerBox atomicgamer.com##.bannerCaption esl.eu,foodnetwork.ca,macworld.co.uk,photobucket.com,zoover.co.uk##.bannerContainer cargurus.com##.bannerDiv iberia.com##.bannerGiraffe xda-developers.com##.bannerHolder sastudy.co.za##.bannerHolder728 pixdaus.com##.bannerIdent civiweb.com,thehimalayantimes.com##.bannerLink come2play.com##.bannerLong artistdirect.com##.bannerNavi ewn.co.za##.bannerSecond runnersworld.com##.bannerSub bitsnoop.com##.bannerTitle christianpost.com,jamanetwork.com,londonstockexchange.com,xtri.com##.bannerTop hongkiat.com##.bannerWrap iphoneapplicationlist.com,salon.com,shockwave.com##.bannerWrapper impawards.com##.banner_2 canalboat.co.uk##.banner_234 impawards.com##.banner_3 mygaming.co.za,travelpulse.com##.banner_300 kohit.net,mygaming.co.za##.banner_468 komp3.net##.banner_468_holder pastebin.com,ratemyteachers.com##.banner_728 uploadstation.com##.banner_area cbssports.com##.banner_bg business-standard.com##.banner_block anyclip.com##.banner_bottom aww.com.au,englishrussia.com,softonic.com##.banner_box coda.fm,jamieoliver.com,smartcompany.com.au,take.fm##.banner_container kyivpost.com##.banner_content_t pricespy.co.nz##.banner_div swapace.com##.banner_foot tvtechnology.com##.banner_footer domainmasters.co.ke##.banner_google arabtimesonline.com,silverlight.net##.banner_header rugby365.com##.banner_holder newsy.com##.banner_holder_300_250 cfos.de##.banner_left livecharts.co.uk##.banner_long expressindia.com##.banner_main plussports.com##.banner_mid checkoutmyink.com##.banner_placer 977music.com,seenow.com##.banner_right dhl.de##.banner_right_resultpage_middle statista.com##.banner_skyscraper 977music.com,rnews.co.za,seetickets.com,thestranger.com##.banner_top porttechnology.org##.banner_wrapper gamenet.com##.bannera zeenews.india.com##.bannerarea sj-r.com,widih.org##.bannerbottom bloomberg.com##.bannerbox timesofoman.com##.bannerbox1 timesofoman.com##.bannerbox2 fashionotes.com##.bannerclick arcadebomb.com##.bannerext breakfreemovies.com,fifaembed.com,nowwatchtvlive.com,surk.tv,tvbay.org##.bannerfloat 2mfm.org,aps.dz,beginlinux.com,eatdrinkexplore.com,fleetwatch.co.za,gameofthrones.net,i-programmer.info,killerdirectory.com,knowthecause.com,maravipost.com,mousesteps.com,onislam.net,rhylfc.co.uk,russianireland.com,soccer24.co.zw,thesentinel.com,vidipedia.org##.bannergroup brecorder.com##.bannergroup_box vidipedia.org##.bannergroup_menu malaysiandigest.com##.bannergroup_sideBanner2 dailynews.co.tz##.bannergroup_text av-comparatives.org,busiweek.com,caribnewsdesk.com,israel21c.org,planetfashiontv.com,uberrock.co.uk##.banneritem elitistjerks.com##.bannerl0aded racing-games.com,widih.org##.bannerleft techspot.com##.bannernav digitalproductionme.com,racing-games.com,widih.org##.bannerright c21media.net,classicsdujour.com,filezoo.com,general-search.net,igirlsgames.com,jobstreet.com.my,jobstreet.com.sg,kdoctv.net,lolroflmao.com,mysteriousuniverse.org,phuketgazette.net,sheknows.com,telesurtv.net,thinkdigit.com##.banners wlrfm.com##.banners-bottom-a codecs.com##.banners-right ecr.co.za,jacarandafm.com##.banners120 thinkdigit.com##.banners_all dinnersite.co.za##.banners_leaderboard wdna.org##.banners_right cbc.ca##.bannerslot-container musictory.com,widih.org##.bannertop urlcash.org##.bannertop > center > #leftbox goldengirlfinance.ca##.bannerwrap myhostnews.com##.bannerwrapper_t 4v4.com,bn0.com,shieldarcade.com##.banr askqology.com##.bar desimartini.com##.basebox[style="height:435px;"] premiershiprugby.com##.basesky tomshardware.com##.basicCentral-elm.partner coolspotters.com##.bau-flag bbc.co.uk##.bbccom_companion bbc.co.uk,bbc.com##.bbccom_sponsor ecommercetimes.com,ectnews.com,linuxinsider.com,macnewsworld.com,technewsworld.com##.bbframe bbgsite.com##.bbg_ad_fulltop bbgsite.com##.bbg_ad_side search.yahoo.com##.bbox foodnetwork.ca##.bboxContainer h-online.com##.bcadv fakenamegenerator.com##.bcsw iol.co.za##.bd_images publicradio.org##.become-sponsor-link wgbh.org##.becomeSponsor westernjournalism.com##.before-article mouthshut.com##.beige-border-tr[style="padding:5px;"] goodgearguide.com.au##.bestprice-footer football365.com##.bet-link soccerway.com##.bet-now-button-container vipbox.tv##.bet365-caption skysports.com##.betlink lshunter.tv##.bets racinguk.com##.bets_companies_logos goal.com##.betting goal.com##.betting-odds goal.com##.betting-widget-default-2 sportinglife.com##.betting_link broadcastnewsroom.com##.bfua flixflux.co.uk##.bgBlue playgroundmag.net##.bg_link bryanreesman.com##.bg_strip_add biblegateway.com##.bga biblegateway.com##.bga-footer search.yahoo.com##.bgclickable overclock3d.net##.bglink entrepreneur.com##.bgwhiteb siouxcityjournal.com##.bidBuyWrapperLG download.cnet.com##.bidWarContainer cnet.com,techrepublic.com,zdnet.com##.bidwar findarticles.com##.bidwarCont furiousfanboys.com,regretfulmorning.com,viva.co.nz##.big-banner torontolife.com##.big-box family.ca##.big-box-container chipchick.com,megafileupload.com,softarchive.net##.big_banner tomwans.com##.big_button[target="_blank"] toblender.com##.bigadd softpile.com##.bigadvs wasterecyclingnews.com##.bigbanner comicbookresources.com,flyerland.ca,healthcentral.com,knoxnews.com,mysuburbanlife.com,nowtoronto.com,tcpalm.com,tiff.net##.bigbox tucsoncitizen.com##.bigbox_container caller.com,commercialappeal.com,courierpress.com,gosanangelo.com,govolsxtra.com,independentmail.com,kitsapsun.com,knoxnews.com,naplesnews.com,redding.com,reporternews.com,tcpalm.com,timesrecordnews.com,vcstar.com##.bigbox_wrapper exclaim.ca##.bigboxhome tri247.com##.biglink wctk.com##.bigpromo about.com,edmunds.com,motherjones.com,pep.ph,todaysbigthing.com##.billboard bre.ad##.billboard-body eztv.ch##.bitx-button mywesttexas.com,ourmidland.com,theintelligencer.com##.biz-info yelp.be,yelp.ca,yelp.ch,yelp.co.nz,yelp.co.uk,yelp.com,yelp.com.au,yelp.com.sg,yelp.ie##.biz-photos-yloca slate.com##.bizbox_promo scienceworldreport.com##.bk-sidebn arsenalnews.co.uk##.bkmrk_pst_flt uvnc.com##.black + table[cellspacing="0"][cellpadding="5"][style="width: 100%;"]:last-child nowsci.com##.black_overlay kioskea.net##.bloc_09 jobmail.co.za##.block-AdsByJobMail ap.org##.block-ap-google-adwords bravotv.com##.block-bravo_sponsored_links biosciencetechnology.com,dinnertool.com,ecnmag.com,fastcocreate.com,fastcoexist.com,fastcompany.com,hollywoodreporter.com,lifegoesstrong.com,manufacturing.net,midwestliving.com,nbcsports.com,pddnet.com,petside.com,sfbg.com,theweek.co.uk,todayonline.com##.block-dart ap.org,expertreviews.co.uk,fitpregnancy.com,itpro.co.uk,newsweek.com,weta.org##.block-dfp reflector.com##.block-dfp_plugin examiner.com##.block-ex-dart voxy.co.nz##.block-featured_offers foxnews.com##.block-fox_yume jobmail.co.za##.block-gads globalgrind.com##.block-gg_dfp gardensillustrated.com,historyextra.com##.block-im_dfp androidcentral.com##.block-mbn-offers megagames.com##.block-megagames-header-ad visitpa.com##.block-mmg-oas motogp.com##.block-motogp_adserver pddnet.com##.block-panels-mini philstar.com##.block-philstar-ad praguemonitor.com##.block-praguetvads football-espana.net,football-italia.net##.block-story-footer-simag-banner accesshollywood.com##.block-style_deals autoexpress.co.uk##.block-taboola laboratoryequipment.com##.block-title ibtimes.com##.block-x90 augusta.com##.block-yca_plugin worldtimebuddy.com##.block2 macmusic.org##.block440Adv alternativeto.net##.blockReplace ilix.in##.blockUI torrentz.cd##.block_10_full miniclip.com##.block_300x250 miniclip.com##.block_300x250_holder miniclip.com##.block_300x250_sketchstar soccerway.com##.block_match_widget_wrapper-wrapper torrentz.cd##.block_tor_loc_full filesharingtalk.com##.blocked dutchnews.nl##.blockleft gametracker.com##.blocknewhdrad economist.com##.blog-sponsor siliconvalley.com##.blogBox pxleyes.com##.blogpostbanner redbookmag.com##.blogs_2_circ_offer animeflv.net##.bloque_pos napavalleyregister.com,pantagraph.com##.blox-leaderboard-container downeu.net##.blq:first-child mnn.com##.blue-bottom 4shared.com##.blueBanner fleetwatch.co.za##.blue_yjsg2_out fleetwatch.co.za##.blue_yjsg4_out bitcointalk.org##.bm-main usairways.com##.bmodule adlock.in##.bn christianpost.com,parentherald.com##.bn728 ibtimes.co.uk,ibtimes.com##.bn_center_bottom_leaderboard_hd tinydl.link##.bnner demonoid.pw##.bnnr_top electronicsfeed.com,gatorzone.com,intelligencer.ca##.bnr euroweek.com##.bnr-top carnewschina.com,thetycho.com##.bnr728 informer.com##.bnr_block forbes.com##.body > p > a[href^="http://www.newsletters.forbes.com/store?"] mangahere.com##.body-bg-left mangahere.com##.body-bg-right cheatcc.com##.body-side-banner billboard.biz##.bodyContent[style="padding-bottom:30px; text-align: center"] news.am##.bodybnr468 barrons.com##.boldGreyNine frommers.com##.book-a-trip biblegateway.com##.bookperks-section cmo.com.au,interiordesign.net##.boombox bangkokpost.com##.boomboxSize1 overclock3d.net##.border-box-320 thenextweb.com##.border-t.mt-2 share-links.biz##.border1dark bitcointalk.org##.bordercolor[width="100%"][cellspacing="0"][cellpadding="0"][border="0"] > tbody > tr[class^="h"] > td[class^="i"] extratorrent.cc##.borderdark[style="padding: 5px;"] helenair.com##.bordered[align="center"][width="728"] afreecodec.com##.bornone tgun.tv##.bossPlayer dailynews.gov.bw##.bot-banner trueslant.com##.bot_banner gofish.com##.botban1 gofish.com##.botban2 bankrate.com##.botbanner pixdaus.com##.bottom eplans.com,liligo.com,reverso.net,spanishdict.com##.bottom-banner livehdq.info##.bottom-bar kaskus.co.id##.bottom-frame usatoday.com##.bottom-google-links photographyreview.com##.bottom-leaderboard theticketmiami.com##.bottom-super-leaderboard weatheroffice.gc.ca##.bottomBanner softicons.com##.bottom_125_block softicons.com##.bottom_600_250_block themoscowtimes.com##.bottom_banner secdigitalnetwork.com##.bottom_banners_outer gamenguide.com##.bottom_bn einthusan.com##.bottom_leaderboard einthusan.com##.bottom_medium_leaderboard einthusan.com##.bottom_small_leaderboard broadcastnewsroom.com,mumbaimirror.com,softonic.com##.bottombanner arcadebomb.com##.bottombox technologizer.com##.bottompromo explainthatstuff.com##.bottomsquare filediva.com##.bouton jpost.com##.box-banner-wrap oilprice.com##.box-news-sponsor phonedog.com##.box-rail-skyleft phonedog.com##.box-rail-skyright accuratefiles.com##.box-result oilprice.com##.box-sponsors webupd8.org##.box-top bmwblog.com##.box-top-leaderboard fins.com##.box.shadeA malaysiastory.com,wahm.com##.box2 fins.com##.box2.shadeB senmanga.com##.box300x250 mediadump.com##.box336 senmanga.com##.box480x90 trendhunter.com##.box600Container jekoo.com##.boxItem yahoo.com.au##.boxMidRt.pB0 efe.com##.boxPubli efe.com##.boxPubliBlanco fliiby.com##.box_300x250 brunei-online.com.bn##.box_banner bmwblog.com##.box_banners_125 al.com,cleveland.com,masslive.com,mlive.com,nj.com,nola.com,pennlive.com##.box_grayoutline findicons.com##.box_info ashampoo.com##.box_recommend2 lyricsmania.com##.boxcontent1 elitistjerks.com##.boxl0aded downloadbox.to##.boxpanjang brainyquote.com##.bq_ad_320x250_multi apa.az##.br-panel hardware.info##.br_top_container brothersoft.com##.brand washingtonpost.com##.brand-connect-module mapquest.com##.brandedBizLocSprite primedia.co.za##.branding-sponsor csoonline.com##.brandposts 1310news.com,680news.com,news1130.com##.breaking-news-alerts-sponsorship-block break.com##.breaking_news break.com##.breaking_news_wrap thedailybeast.com##.breakout-item break.com##.brk_ldrbrd_wrap techtipsgeek.com##.bsa-banner karachicorner.com##.bsa180 karachicorner.com##.bsa300 karachicorner.com##.bsa336 twtmore.com##.bsa_wrap bloggertemplateplace.com##.bsainpost mysteriousuniverse.org,wbond.net##.bsap easyvectors.com,mangable.com,textmechanic.com,tutorial9.net,webdesign.org,winrumors.com##.bsarocks if-not-true-then-false.com##.bsarocks[style="height:250px;margin-left:20px;"] if-not-true-then-false.com##.bsarocks[style="height:520px;"] mmorpg.com##.bsgoskin webopedia.com##.bstext virginradiodubai.com##.bt-btm fenopy.se##.bt.dl milesplit.com##.btf idolator.com##.btf-leader gamepedia.com,minecraftwiki.net##.btflb diply.com##.btfrectangle dubai92.com,dubaieye1038.com##.btm-banner cricwaves.com##.btm728 helensburghadvertiser.co.uk,the-gazette.co.uk##.btn isohunt.to##.btn-bitlord mp3truck.net##.btn-danger bitlordsearch.com##.btn-download-bitlord adlock.in##.btn-info torrents.net##.btn3 clip.dj##.btnDownloadRingtone whosampled.com##.btnRingtoneTrack legendarydevils.com##.btn_dl wrc.com##.btns wrc.com##.btnswf gizmodo.com.au##.btyb_cat whitepages.com##.business_premium_container_top switchboard.com,whitepages.com##.business_premium_results torrentbit.net##.but_down_sponsored 1053kissfm.com##.button-buy torrentbit.net##.button-long miloyski.com##.button[target="_blank"] darelease.com,downarchive.com,keygenfree.org,mechodownload.com##.button_dl freedownloadmanager.org,freedownloadscenter.com##.button_free_scan 923jackfm.com,chez106.com,country1011.com,country1043.com,country600.com,foxradio.ca,kissnorthbay.com,kisssoo.com,listenlive.co,npr.org,thesoundla.com,tunegenie.com##.buy cpuboss.com,gpuboss.com,ssdboss.com##.buy-button awdit.com##.buy-link overclock.net##.buy-now air1.com##.buyIcon klove.com##.buyPanel listenlive.co##.buySong securenetsystems.net##.buybutton zdnet.com##.buying-choices-2 trendir.com##.buyit avsforum.com##.buynow morningstar.com##.buyout_leader_cont bangkokpost.com##.buzzBoombox guanabee.com##.buzzfeedSubColPod buzzillions.com##.bz-model-lrec farmanddairy.com##.c-position-in-story businessdailyafrica.com,nation.co.ke,theeastafrican.co.ke##.c15r nationmultimedia.com##.c2Ads maniacdev.com##.c4 canada411.ca##.c411TopBanner dealsonwheels.co.nz,farmtrader.co.nz,motorcycletrader.co.nz,tradeaboat.co.nz##.cBanner brisbanetimes.com.au,theage.com.au,watoday.com.au##.cN-storyDeal filepuma.com##.cRight_footer smh.com.au,theage.com.au,watoday.com.au##.cS-compare smh.com.au##.cS-debtBusters google.com,~mail.google.com##.c[style="margin: 0pt;"] uploading.com##.c_2 ria.ru##.c_banners mmosite.com##.c_gg nst.com.my##.cadv streamtv1.in##.caf bonniegames.com##.caja_juegopubli winnipegfreepress.com##.cal-sponsor ieee.org##.callOutTitle katu.com,keprtv.com,komonews.com,kval.com,kvi.com,star1015.com##.callout hgtvremodels.com##.cap dummies.com,tribe.net##.caption lonelyplanet.com##.card--sponsored care2.com##.care2_horiz_adspace receeve.it##.carousel youtube.com##.carousel-offer-url-container theberry.com,thechive.com##.carousel-sponsor ludobox.com##.carrepub overstock.com##.cars-ad-localdeals hindilinks4u.to##.cat-featured 123peppy.com##.cat-spacer horsedeals.co.uk##.catalogueRightColWide runnow.eu##.category-retail dealbreaker.com##.category-sponsored-content girlsgogames.co.uk,girlsgogames.com##.categoryBanner retailmenot.com##.categorySponsor kibagames.com##.category_adv_container oliveoiltimes.com##.category_advert mega-search.me##.catfish getprice.com.au##.catin_side_mrec coolspotters.com##.cau bitcoinreviewer.com##.cb-footer-a > .cb-one > #text-4 bitcoinreviewer.com##.cb-footer-a > .cb-two > #text-5 cryptocoinsnews.com##.cb-sidebar > #text-107 cryptocoinsnews.com##.cb-sidebar > #text-44 cryptocoinsnews.com##.cb-sidebar > #text-56 cryptocoinsnews.com##.cb-sidebar > #text-61 cryptocoinsnews.com##.cb-sidebar > #text-66 cryptocoinsnews.com##.cb-sidebar > #text-84 cryptocoinsnews.com##.cb-two > #text-38 cbc.ca##.cbc-adv-wrapper cbc.ca##.cbc-big-box-ad cbc.ca##.cbc-promo-sponsor careerbuilder.com##.cbmsnArticleAdvertisement wcco.com##.cbstv_top_one_column givemefile.net##.ccb_cap_class_1 bigwhite.com##.ccm-image-block inquirer.net##.cct-extended-ribbon orange.co.uk##.ce-mpu toptenreviews.com##.ceh_top_ad_container nick.com##.celebrity-sponsored mybrute.com##.cellulePub playwinningpoker.com##.centban port2port.com,privateproperty.co.za##.centerBanner siberiantimes.com##.centerBannerRight bookcrossing.com##.center[style="width:260px;"] bookcrossing.com##.center[style="width:620px;"] zippyshare.com##.center_reklamy sulekha.com##.centxt cfake.com##.cfakeSponsored yumfoodrecipes.com##.cfmonitor cfo.com##.cfo_native_ad howstuffworks.com,internet.com##.ch ustream.tv##.channelTopBannerWrapper symptomfind.com##.channelfav businessinsider.com##.chartbeat forum.xda-developers.com##.checkOut motorauthority.com##.chitika-listings 4shared.com##.christmasBanner wsj.com##.cioMypro-marketing newsfactor.com##.cipText search.com##.citeurl 4shared.com##.citrioPromoLink post-gazette.com##.city-coupons-wrap crooksandliars.com##.cl_ad_blocks-5 crooksandliars.com##.cl_ad_blocks-6 crooksandliars.com##.clam-google crooksandliars.com##.clam-text telegraph.co.uk##.classifiedAds uploading.com##.cleanlab_banner clgaming.net##.clg-footerSponsors yourepeat.com##.click-left yourepeat.com##.click-right haaretz.com##.clickTrackerGroup infobetting.com##.click_bookmaker thinkbroadband.com##.clickable-skin windowsitpro.com##.close abconline.xyz##.close9 wftv.com##.cmFeedUtilities ajc.com##.cmSponsored wsbtv.com##.cmSubHeaderWrap wftv.com##.cmToolBox ew.com##.cmWrapper macleans.ca##.cmg_walrus geektyrant.com##.cmn-side 2dopeboyz.com##.cmn728x90 motorsport.com##.cmpFixedBox cnn.com##.cnnMosaic160Container cnn.com##.cnnPostAdHolder nascar.com##.cnnUpfrontContainer cnn.com##.cnn_SRLTbbn336a cnn.com##.cnn_cnn_widget_adtag cnn.com##.cnn_elxad300spc cnn.com##.cnn_sectprtnrbox_grpn325 europeancarweb.com,hotrod.com,truckinweb.com##.cnt-google-links-container truckinweb.com##.cnt-google-wide europeancarweb.com,hotrod.com##.cnt-sponsored-showcase icanbecreative.com##.codeg ebookee.org##.codemain ebookee.org##.codetop disqus.com##.col-promoted euronews.com##.col-pub-skyscraper 3v3.gg##.col-right2.mt10 a[target="_blank"] nycgo.com##.colBBox shopping.aol.com##.col_asl jamendo.com##.col_extra naukri.com##.collMTp au.news.yahoo.com##.collection-sponsored querverweis.net##.column-box > .column-box:first-child + .column-box[style="padding-top:10px"] reverso.net##.columnBanner2 arcadebomb.com##.colunit1 telegraph.co.uk##.comDatingWidget telegraph.co.uk##.comPuff worldstarhiphop.com##.comhead2 + .iframe[style="height:250px"] expat-blog.com##.comlnk googlesightseeing.com##.comm-skyscraper googlesightseeing.com##.comm-square abovethelaw.com##.comments-sponsor tripadvisor.ca,tripadvisor.co.uk,tripadvisor.com,tripadvisor.ie,tripadvisor.in##.commerce prevention.com##.commerce-block capitalfm.com,capitalxtra.com,heart.co.uk,independent.co.uk,runningserver.com,smoothradio.com,standard.co.uk,thisislondon.co.uk,xfm.co.uk##.commercial sheptonmalletjournal.co.uk##.commercial-promotions independent.co.uk##.commercialpromo heraldnet.com##.comp_DailyDealWidget verizon.com##.comp_container_marketplace blinkbox.com##.companion 5min.com##.companion-banner bbyellow.com,bsyellow.com,businessdirectory.mu,businesslist.ae,businesslist.co.cm,businesslist.co.ke,businesslist.co.ug,businesslist.com.bd,businesslist.com.ng,businesslist.hk,businesslist.my,businesslist.net.nz,businesslist.ph,businesslist.pk,businesslist.sg,businesslist.tw,businesslist.vn,cambodiayp.com,caymanyellow.com,chileindex.com,colombiayp.com,dominicanyp.com,egypyp.com,ethiopiadirectory.com,georgiayp.com,ghanayp.com,indonesiayp.com,jmyellow.com,jpyellow.com,lebyp.com,lesothoyp.com,localbotswana.com,malawiyp.com,moroccoyp.com,myanmaryp.com,namibiayp.com,nepalyp.com,onlinebusinesslist.co.za,puertoricoindex.com,qataryp.com,rwandayp.com,saudianyp.com,senegalyp.com,sudanyp.com,tanzaniayp.com,thaigreenpages.com,tntyellow.com,tunisiayp.com,turkishyp.com,venezuelayp.com,yemenyp.com,zambiayp.com,zimbabweyp.com,zipinfo.in##.company_banner versusio.com##.compare_leaderboard delish.com,msn.com##.conban1 msn.com##.condbanner2 theglobeandmail.com##.conductor-links thegameslist.com##.cont spoonyexperiment.com##.cont_adv torrent-finder.info##.cont_lb babylon.com,searchsafer.com##.contadwltr miniclip.com##.container-300x250 ina.fr##.container-pubcarre jokersupdates.com##.container_contentrightspan tourofbritain.co.uk##.container_right_mpu bbh.cc##.content + .sidebar adfoc.us##.content > iframe flashgot.net##.content a[rel="nofollow"][target="_blаnk"] intouchweekly.com##.content-banner crmbuyer.com,ectnews.com,linuxinsider.com,macnewsworld.com,technewsworld.com##.content-block-slinks songlyrics.com##.content-bottom-banner 1049.fm##.content-footer-promo pwinsider.com##.content-left pcmag.com##.content-links funnyordie.com##.content-page-mrec funnyordie.com##.content-page-mrec-container mysuburbanlife.com##.content-promo newstalkzb.co.nz##.content-promos kiz10.com##.content-recomendados pwinsider.com##.content-right crmbuyer.com,ectnews.com,linuxinsider.com,macnewsworld.com,technewsworld.com##.content-tab-slinks fijilive.com##.content-top futuresmag.com##.content-top-banner yellowpages.bw,yellowpages.co.ls,yellowpages.co.zm##.contentBannerHolderLarge girlsgogames.com##.contentListSkycontainer seocentro.com##.contentTDRight[valign="top"] > table[width="280"][border="0"][align="center"][cellspacing="0"][cellpadding="2"]:first-child kohit.net##.content_banner_right gamefront.com##.content_bottom_cap domainnamewire.com##.content_posts_promotion globrix.com##.content_slots_for_results_container iafrica.com##.content_sponsoredLinksBox videobull.com##.contentlinkspecial goodgearguide.com.au,pcworld.idg.com.au##.contentpage-boombox nexus404.com##.contentpostTAD sc2ranks.com##.contentright coinurl.com##.contents huffingtonpost.com##.contin_below businessinsider.com##.continue-link netnewscheck.com##.continue-text notcot.org##.conversationalist_outer list25.com##.converter sharaget.com##.coollist columbian.com##.coupon-widget wnst.net##.coupon_block ftadviser.com##.cpdSponsored politicalwire.com##.cqheadlinebox merriam-webster.com##.creative-300_BOT-container merriam-webster.com##.creative-300_TOP-container plus.im##.creativeWrapper cgsociety.org##.creditcardAD forumpromotion.net##.crm[style="text-align: left;"] wric.com##.csWxSponsor celebuzz.com##.cs_banner728_top candystand.com##.cs_square_banner candystand.com##.cs_tall_banner candystand.com##.cs_wide_banner carsales.com.au##.csn-ad-preload vitorrent.net##.css_btn_class_fast columbian.com##.cta[style="margin-top: -10px;"] terra.com##.ctn-tgm-bottom-holder funny.com##.ctnAdBanner homefinder.com##.cubeContainer cramit.in##.curved_box_no_shadow[style="width:977px;"] forumpromotion.net##.custom-foot + .forumbg2 101cargames.com##.custom-siteskin malwarehelp.org##.custom_1_box annistonstar.com##.custom_hot_deal_image jobhits.co.uk##.cvads cocomment.com##.cw_adv glumbouploads.com##.d0_728 rapidok.com##.d_content[style="background:#FFFFFF url(/img/d1.gif) repeat-x scroll 0 86%;"] thomasnet.com##.da diply.com##.da-disclaimer arabianindustry.com##.da-leaderboard torrents.to##.da-top thedailywtf.com##.daBlock tesco.com##.dart allmovie.com##.dart-skyscraper americanphotomag.com,ecnmag.com,manufacturing.net,webuser.co.uk##.dart-tag wetv.com##.dart300x250Border orange.co.uk##.dartlabel torrent.cd##.data[style="margin-bottom: 0px; margin-top: 15px;"] mrarrowhead.com##.dating_site_banner itv.com##.db-mpu foobar2000.org##.db_link herald.co.zw##.dban dbforums.com##.dbfSubscribe[style^="display: block; z-index: 1002; "] startups.co.uk##.dc-leaderboard kibagames.com##.dc_color_lightgreen.dc_bg_for_adv ohiostatebuckeyes.com##.dcad elitistjerks.com##.dcc gas2.org##.dd_outer + p + center + br + br + p + table trutv.com##.ddad bts.ph,btscene.eu##.ddl_det_anon btscene.eu##.ddl_srch hdtvtest.co.uk##.deal azstarnet.com,poststar.com,wcfcourier.com##.deal-container kmov.com##.dealLeft kmov.com##.dealRight msnbc.msn.com,nbcnews.com##.deals pcworld.idg.com.au##.deals-box kusports.com##.deals_widget macobserver.com##.dealsontheweb smh.com.au##.debtBusters smashingmagazine.com,tripwiremagazine.com##.declare delfi.lt##.delfi-ads-block wsj.com##.deloitte_disclaimer softpile.com##.desadvs mindspark.com,myway.com,mywebsearch.com##.desc mysearch.com##.desc > div good.is##.description northjersey.com##.detail_boxwrap northjersey.com##.detail_pane_text mp3juices.com##.details + span[style="font-size:80%;"]:last-child heroturko.me##.detay onlinerealgames.com##.df3 marinmagazine.com,scpr.org,shop.com,urbandictionary.com##.dfp premier.org.uk,premierchildrenswork.com,premierchristianity.com,premierchristianradio.com,premiergospel.org.uk,premieryouthwork.com##.dfp-block healthline.com##.dfp-lb-wrapper techradar.com##.dfp-leaderboard-container greatist.com,neurope.eu##.dfp-tag-wrapper sodahead.com##.dfp300x250 sodahead.com##.dfp300x600 ket.org##.dfp_primary imdb.com##.dfp_slot premier.org.uk,premierchildrenswork.com,premierchristianity.com,premierchristianradio.com,premiergospel.org.uk,premieryouthwork.com##.dfp_strip dafont.com##.dfsmall[style="background:#fff"] dafont.com##.dfxsmall[style="text-align:right;color:#999"] hpcwire.com##.diana reference.com##.dic_bk zdnet.com##.dirListSuperSpons 1337x.to,flmsdown.net,torrentdownloads.net,vertor.com##.direct fenopy.unblock.pro,unblock-proxybunker.co.uk##.direct-dl 1337x.org##.directDL kat.ph##.directDownloadButton seedpeer.eu,sumotorrent.sx##.directStreaming sumotorrent.sx##.directStreamingText softarchive.net##.direct_download world-airport-codes.com##.directory-airport news.com.au##.disclaimer-footer chacha.com##.disclosure 1cookinggames.com,yokogames.com##.displaygamesbannerspot3 hellopeter.com##.div1 hellopeter.com##.div2 espncricinfo.com##.div300Pad aniweather.com##.divBottomNotice aniweather.com##.divCenterNotice alternativeto.net##.divLeaderboardLove israelnationalnews.com##.divTopInBox hellobeautiful.com##.diversity-one-widget search.ovguide.com##.dl:first-child mediafire.com##.dlInfo-Apps bitsnoop.com##.dl_adp bitsnoop.com##.dl_alt2 download3k.com##.dl_button bitsnoop.com##.dl_bv bitsnoop.com##.dl_secure torrentcrazy.com##.dlf free-tv-video-online.me##.dloadf free-tv-video-online.me##.dloadh free-tv-video-online.me##.dloadt orlydb.com##.dlright dreammining.com##.dm-adds dailymotion.com##.dmpi_masscast isup.me##.domain + p + center:last-child > a:first-child i4u.com##.dotted gearlive.com##.double techtipsgeek.com##.double-cont bigtop40.com,capitalfm.com,capitalxtra.com,dirtymag.com,kingfiles.net,win7dl.com##.download torrents.de,torrentz.ch,torrentz.com,torrentz.eu,torrentz.in,torrentz.li,torrentz.me,torrentz.ph,torrentz.unblockt.com##.download > h2 + dl > dd turbobit.net##.download-area-top host1free.com##.download-block generalfiles.me##.download-button awdit.com##.download-right-add turbobit.net##.download-top torentilo.com##.downloadBlock > .downloadButton wupload.com##.downloadOptionFooter tubeplus.me##.download_emule candystand.com##.download_free_games_ad fileshut.biz,fileshut.com##.download_item2 download-movie-soundtracks.com##.download_link > .direct_link fileserve.com##.download_meagaCloud primewire.ag##.download_now_mouseover load.to##.download_right filediva.com##.download_top fileshut.biz,fileshut.com##.download_top2 brothersoft.com##.downloadadv brothersoft.com##.downloadadv1 brothersoft.com##.downloadadv3 defenseindustrydaily.com##.downloads vertor.com##.downweb billionuploads.com##.dowpdb vcdq.com##.dp-widget equestriadaily.com##.drgwefowiehfoiwe ashampoo.com##.driverupdater movietrailers.yt##.drt journalnow.com##.dt_mod digitaltrends.com##.dtads-slot googleping.com,search.com##.dtext darkreading.com##.dualRight dressupcraze.com##.duc-160 dressupcraze.com##.duc-728 bloomberg.com##.dvz-widget-sponsor webmd.com##.dynbm_wrap espnwatch.tv##.dzt watchreport.com##.e3lan300_250-widget stream2watch.com##.ea search.yahoo.com##.eadlast cnet.com.au##.ebay amateurphotographer.co.uk##.ebay-deals carandclassic.co.uk##.ebayRSS gumtree.com##.ecn-display-block ecosia.org##.ecolink-search-result teenvogue.com##.ecom-placement smashingmagazine.com##.ed smashingmagazine.com##.ed-us timeoutabudhabi.com##.editoral_banner dailymail.co.uk##.editors-choice.ccox.link-ccox.linkro-darkred experts-exchange.com##.eeAD bostonmagazine.com##.eewidget notebooks.com##.efbleft facebook.com##.ego_spo priceonomics.com##.eib-banner lyrster.com##.el_results playbill.com##.embedded-banner soccerstand.com##.enet_banner_container moviefone.com##.ent_promo_sidetexttitle lfpress.com##.entertainmentSponsorshipContainer cryptocoinsnews.com##.entry-content > center > .mobile cbslocal.com,radio.com##.entry-injected-block radaronline.com##.entry-meta > div[style="width:637px;height:224px;"] infoq.com##.entrysponsors wrytestuff.com##.eoc250 electronicproducts.com##.ep-boombox-advertisment msnbc.msn.com,nbcnews.com##.eshopStory easyvoyage.co.uk##.esv-pub-300-250 searchenginejournal.com##.even miami.com##.expedia-widget nytimes.com##.expediaBooking mercurynews.com##.expertBox ddlvalley.net##.ext-link cryptocoinsnews.com,torrents.net##.external smithsonianmag.com##.external-associated-products realestate.co.nz##.externalLinkBar thefinancialexpress-bd.com##.extraLink tucows.com##.f11 india.com##.fBannerAside computerworld.co.nz##.fairfax_nav inturpo.com##.fake_embed_ad_close flixflux.co.uk##.fan commentarymagazine.com##.fancybox-wrap freshwap.net##.fast might.net##.fat-container smarter.com##.favboxmiddlesearch smarter.com##.favwrapper facebook.com##.fbAdUnit facebook.com##.fbEmu facebook.com##.fbEmuBlock facebook.com##.fbEmuComboList facebook.com##.fbEmuEgo facebook.com##.fbEmuEgoUnit facebook.com##.fbEmuLink facebook.com##.fbPhotoAdsCol facebook.com##.fbTimelineSideAds tormovies.org##.fbd-banner sharkscope.com##.fbstyle bankrate.com##.fcAdGrey webcenters.netscape.compuserve.com##.fcCntnr ebay.com##.fdad1 firedrive.com##.fdad_container investopedia.com##.fe-sponsorbox ghanaweb.com##.featLks reason.com##.feature wowheadnews.com##.feature-aside findthatfile.com,lifestyle.yahoo.com,simplyhired.com,yellowpages.com##.featured recombu.com##.featured-deal sidereel.com##.featured-episode-link everydayhealth.com##.featured-group siliconrepublic.com##.featured-partners pcauthority.com.au##.featured-retailers geekwire.com##.featured-sponsor top1000.ie##.featured300x260 24hrs.ca,lfpress.com##.featuredBusinesses infoworld.com##.featuredSponsor-strip whitepages.ae##.featured_companies_bg_main mousebreaker.com##.featured_games_band candystand.com##.featured_partners_title id-box.biz##.featuredlinksBox olx.co.nz##.featuredtitlepremium india.com##.ff-sponser cnn.com##.fg_presentedBy stuff.tv##.field-field-promo-node-teaser avaxhm.com,avaxhome.ws##.file-express rapidlibrary.com##.file-recommend rapidlibrary.com##.file-urls rapidlibrary.com##.file-urls2 kdvr.com##.filler cokeandpopcorn.com##.filler728 dailyfinance.com##.finance-partners adn.com,bellinghamherald.com,bnd.com,bradenton.com,centredaily.com,enquirerherald.com,fortmilltimes.com,fresnobee.com,heraldonline.com,idahostatesman.com,islandpacket.com,kentucky.com,lakewyliepilot.com,ledger-enquirer.com,macon.com,mercedsunstar.com,modbee.com,myrtlebeachonline.com,newsobserver.com,sanluisobispo.com,sunherald.com,thestate.com,tri-cityherald.com##.findnsave_combo katu.com##.fisher468 flashvids.org,wfgo.net##.fixe facebook.com##.fixedAux .pbm belgie.fm,danmark.fm,deutschland.fm,england.fm,espana.fm,india.fm,italia.fm,lafrance.fm,nederland.fm,norge.fm,polskafm.pl,sverige.fm,thestates.fm##.fl.banbo belgie.fm,danmark.fm,deutschland.fm,england.fm,espana.fm,india.fm,italia.fm,lafrance.fm,nederland.fm,norge.fm,polskafm.pl,sverige.fm,thestates.fm##.fl.m alwatanvoice.com##.flash-160x600 alwatanvoice.com##.flash-728x90 letitbit.net##.flash-not-found canberratimes.com.au##.flashfloater contactmusic.com##.flexibleLeaderboard tennisearth.com##.flexslider gsmchoice.com##.floatLeft tradekey.com##.float_left notcot.com##.floatbox featve.com,filotv.pw,foxsports-la.com,notcot.com,nowwatchtvlive.com,xuuby.com,zonytvcom.info##.floater treehugger.com##.floater-indiv zylom.com##.floor_wrapper htmldog.com##.flower amctheatres.com##.flt-ad-strut adcrun.ch,bc.vc##.fly_frame newsobserver.com##.focus_box inquirer.net##.fontgraysmall greatbritishlife.co.uk##.foot-banners radiozindagi.com##.foot_top donegaltv.ie##.footer ksstradio.com,spectator.co.uk##.footer-banner directorslive.com##.footer-banner-img torhead.com##.footer-bg wowhead.com##.footer-bgimg xbitlabs.com##.footer-cap people.com,peoplestylewatch.com##.footer-cmad standardmedia.co.ke##.footer-full-banner 931dapaina.com,allmusic.com##.footer-leaderboard thecinemasource.com##.footer-marketgid getswiftfox.com##.footer-right livebasketball.tv##.footer-sponsor sharksrugby.co.za,timestalks.com##.footer-sponsors searchenginejournal.com##.footer-unit btn.com##.footer-widgets hd-trailers.net##.footer-win twentytwowords.com##.footer-zone nickutopia.com##.footer728 thegamingsource.co##.footerBanner wikinvest.com##.footerBrokerageCenter socwall.com##.footerLinks bundesliga.com##.footerPartners londonlovesbusiness.com##.footerPartnerships zynga.com##.footerPromo abc.go.com##.footerRow cartoonnetworkasia.com##.footerWrapper jarkey.net##.footer_728 sundownsfc.co.za##.footer_add jackfm.co.uk,satbeams.com##.footer_banner electronista.com##.footer_content_wrapper maxgames.com##.footer_leaderboard morningstar.in##.footer_links_wrapper scotsman.com##.footer_top_holder datamation.com##.footerbanner eurocupbasketball.com,euroleague.net##.footersponsors-container videojug.com##.forceMPUSize alphacoders.com##.form_info northcoastnow.com##.formy motorhomefacts.com##.forum-promo thewarezscene.org##.forumbg b105.com##.fourSquare_outer bc.vc##.fp-bar-dis autotrader.co.uk##.fpa-deal-header yahoo.com##.fpad tvguide.com##.franchisewrapper freedom.tm##.frdm-sm-ico seedpeer.eu,sumotorrent.sx##.freeDirect watch-series.ag,watch-tv-series.to,watchseries.ph##.freeEpisode empowernetwork.com##.free_video_img megashare.com##.freeblackbox megashare.com##.freewhitebox wharton.upenn.edu##.friend-module spanishcentral.com##.from_spanish_central executivetravelmagazine.com##.ft-add-banner portalangop.co.ao,top1walls.com##.full-banner marilyn.ca##.full-width.leaderboard wikinvest.com##.fullArticleInset-NVAdSlotComponent i4u.com##.fullStoryHeader + .SidebarBox monitor.co.ug##.fullbanner ptinews.com##.fullstoryadd ptinews.com##.fullstorydivright ratebeer.com##.fums webmd.com##.funded_area penny-arcade.com##.funding-horizontal penny-arcade.com##.funding-vertical mattgemmell.com##.fusion_attrib_footer chrisbrownworld.com,myplay.com##.fwas300x250 masterworksbroadway.com##.fwas728x90_top nofilmschool.com##.g-leader prokerala.com##.gAS_468x60 titantv.com##.gAd about.com##.gB free-games.net##.gPBoxAD search.babylon.com##.gRsAdw search.babylon.com##.gRsSlicead claro-search.com,isearch.babylon.com,search.babylon.com##.gRsTopLinks colorgirlgames.com##.g_160X600 popgals.com##.g_adt forum.freeadvice.com##.g_info ambulance-photos.com,bus-and-coach-photos.com,campervan-photos.com,classic-and-vintage-cars.com,construction-and-excavation.com,fire-engine-photos.com,military-vehicle-photos.com,motorcycles-motorbikes.com,oilrig-photos.com,planesandchoppers.com,police-car-photos.com,racing-car-photos.com,shipsandharbours.com,taxi-photos.com,traction-engines.net,tractor-photos.com,train-photos.com,transport-models.com,truck-photos.net,yourboatphotos.com##.ga200[style="width:250px;height:250px;float:right;margin:5px 5px 5px 10px;"] celebrityrumors.com,embarrassingissues.co.uk,page2rss.com##.gad enotalone.com##.gadb snowboarding-essentials.com##.gadbdrtxt gamerant.com##.gads toptenwholesale.com##.gads-home-bottom inserbia.info##.gads250 telegraph.co.uk##.gafs behance.net##.gallery-sponsor citywire.co.uk##.gallerySponsor koreaherald.com##.gallrym[style="margin:15px auto; padding-top:0px;height:130px;"] pcper.com,thedrum.co.uk,thefix.com,tribalfootball.com##.gam-holder 9news.com,bloomberg.com,businessweek.com,courier-journal.com,theleafchronicle.com,thestarpress.com,usaweekend.com##.gam_wrapper addictinggames.com##.gameHeaderSponsor kibagames.com##.game__bottomInfoRightContainer candystand.com##.game_banner_300 muchgames.com##.gamead monstertruckgames.org##.gamecatbox cartoondollemporium.com##.games_dolls_ads_right300x250 adultswim.com##.gametap-placement movieonmovie.com##.gapad moviesplanet.com##.gb canberratimes.com.au##.gbl_advertisementgrey canberratimes.com.au,illawarramercury.com.au##.gbl_disclaimer illawarramercury.com.au##.gbl_section viamichelin.co.uk,viamichelin.com##.gdhBlockV2 geekwire.com##.geekwire_sponsor_posts_widget escapehere.com##.gemini-loaded becclesandbungayjournal.co.uk,burymercury.co.uk,cambstimes.co.uk,derehamtimes.co.uk,dunmowbroadcast.co.uk,eadt.co.uk,edp24.co.uk,elystandard.co.uk,eveningnews24.co.uk,fakenhamtimes.co.uk,greenun24.co.uk,huntspost.co.uk,ipswichstar.co.uk,lowestoftjournal.co.uk,northnorfolknews.co.uk,pinkun.com,royston-crow.co.uk,saffronwaldenreporter.co.uk,sudburymercury.co.uk,thecomet.net,thetfordandbrandontimes.co.uk,wattonandswaffhamtimes.co.uk,wisbechstandard.co.uk,wymondhamandattleboroughmercury.co.uk##.generic_leader greenun24.co.uk,pinkun.com##.generic_sky uefa.com##.geoTargetSponsorHeader health24.com##.get_quote canoe.ca##.getdeals arizonasports.com##.gfp ksl.com##.gfp-slot ktar.com##.gfp300250 mediacoderhq.com##.gg1 bitcomet.com##.gg728 cometbird.com##.gg_250x250 aplus.com##.ggnoads ebay.com##.ggtm gethuman.com##.gh-ads macworld.co.uk##.ghostMpu hotfileserve.ws##.glb-opec bikeradar.com##.global-banner tripadvisor.com##.goLists astro.com##.goad newburytoday.co.uk,thelakewoodscoop.com##.gofollow neogaf.com##.goodie300 neogaf.com##.goodie728 computershopper.com##.goog complaintsboard.com##.goog-border eurodict.com##.googa thenassauguardian.com##.googlAdd 95mac.net,africanadvice.com,appdl.net,freepopfax.com,pspad.com##.google euronews.com##.google-banner nymag.com##.google-bottom zenit.org##.google-dfp news-journalonline.com##.google-entry i-dressup.com##.google-iframe treehugger.com##.google-indiv-box2 rt.com##.google-top-banner 1pic4twenty.co.za##.google160600 downloadatoz.com##.google300_bg downloadatoz.com##.google300_title independent.co.uk##.googleCols inooz.co.uk##.googleContainer dealspl.us##.googleDealBottom complaints.com##.googleTop bridalbook.ph##.google_srec hoobly.com##.googlecont 1pic4twenty.co.za##.googlefat hitfix.com##.googlewide quizlet.com##.googlewrap complaintsboard.com##.googtop whatismyip.com##.gotomypc css3generator.com##.gotta-pay-the-bills disney.com##.gpt belfasttelegraph.co.uk##.grabOnePromo slantmagazine.com##.gray_bg slantmagazine.com##.gray_bgBottom greatandhra.com##.great_andhra_main_add_rotator cool-wallpaper.us##.green businessdictionary.com##.grey-small-link backstage.com##.greyFont teamrock.com##.grid-container-300x250 itproportal.com##.grid-mpu ncaa.com##.grid[style="height: 150px;"] dawn.com##.grid__item.one-whole.push-half.visuallyhidden--palm couriermail.com.au,dailytelegraph.com.au,news.com.au##.group-network-referral-footer eztv-proxy.net,eztv.ch##.gsfc bollywoodtrade.com##.gtable[height="270"][width="320"] 11alive.com,13wmaz.com,9news.com,digtriad.com,firstcoastnews.com,kare11.com,ksdk.com,news10.net,thv11.com,wbir.com,wcsh6.com,wgrz.com,wkyc.com,wlbz2.com,wltx.com,wtsp.com,wusa9.com,wzzm13.com##.gtv_728x90_container waz-warez.org##.guest_adds wheels24.co.za##.gumtree_component animenewsnetwork.com##.gutter kovideo.net##.h-728 themarknews.com##.h-section1 lyricsmode.com##.h113 amw.com,superiorpics.com##.h250 lyricsmode.com##.h253 dealsonwheels.co.nz,farmtrader.co.nz##.hBanner all-shares.com##.hSR keepvid.com##.h[style="padding:0px;width:760px;"] monitor.co.ug,thecitizen.co.tz##.halfbanner blinkbox.com##.halfmpupnl runtastic.com##.halfpage pep.ph##.halfpage-wrapper sbnation.com,theverge.com##.harmony-sponsorship mlb.mlb.com##.has-ads search.yahoo.com##.has-sma-box denverpost.com##.hatad thesimsresource.com##.hb zeefood.in##.hbanner2 chronicle.co.zw,herald.co.zw##.hbanners screenindia.com##.hd webtoolhub.com##.hdShade pbnation.com##.hdrLb pbnation.com##.hdrSq caymannewsservice.com##.head-banner468 vogue.co.uk##.headFullWidth mariopiperni.com,tmrzoo.com##.headbanner bitcoinreviewer.com##.header > .wrap > .cb-large iaminthestore.com##.header > div > div[style="text-align:center;margin:0 auto"] ynaija.com##.header-728 americanfreepress.net,freemalaysiatoday.com,hotfrog.co.uk,islamchannel.tv,ksstradio.com,landandfarm.com,mashable.com,soccer24.co.zw,wow247.co.uk##.header-banner vapingunderground.com##.header-block thedailystar.net##.header-bottom-adds expressandstar.com,guernseypress.com,jerseyeveningpost.com,shropshirestar.com,thebiggestloser.com.au##.header-leaderboard natureasia.com##.header-leaderboard-wrap queenscourier.com##.header-left spyka.net##.header-link times.co.zm##.header-pub lyricsbogie.com,queenscourier.com##.header-right bh24.co.zw##.header-right-banner-wrapper htxt.co.za##.header-sub providencejournal.com,southernliving.com##.header-top astronomynow.com##.header-widget hd-trailers.net##.header-win funnycatpix.com,notsafeforwhat.com,rockdizmusic.com##.header728 onegreenplanet.org##.header728container thelakewoodscoop.com##.headerPromo telegraph.co.uk##.headerThree bastropenterprise.com##.headerTop domainnamewire.com,electricpig.co.uk,gaijinpot.com,squidoo.com##.header_banner kpopstarz.com##.header_bn vidxden.com##.header_greenbar steadyhealth.com##.headerboard bangtidy.net##.headlineapa_base metrolyrics.com##.here hi5.com##.hi5-common-header-banner-ad classiccars.com##.hia_banner 4shared.com##.hiddenshare letitbit.net##.hide-after-60seconds theguardian.com##.hide-on-popup xtshare.com##.hideLink mobilesyrup.com##.hide_768 torentilo.com##.highSpeed all-shares.com##.highSpeedResults siteslike.com##.highlighted dailycurrant.com##.highswiss skins.be##.hint serverfault.com,stackoverflow.com##.hireme ghanaweb.com##.hmSkyscraper hindustantimes.com##.hm_top_right_localnews_contnr_budget 1027dabomb.net##.home-300 broadway.com##.home-leaderboard-728-90 wowhead.com##.home-skin netweather.tv##.home300250 greatdaygames.com##.home_Right_bg wpbt2.org##.home_banners hpe.com##.home_leaderboard justdubs.tv##.home_leftsidbar_add wdwmagic.com##.home_upper_728x90 securitymattersmag.com##.homeart_marketpl_container news1130.com##.homepage-headlines-sponsorship-block mancunianmatters.co.uk##.homepage-leader sunshinecoastdaily.com.au##.homepageContainerFragment independent.co.uk##.homepagePartnerList smashingmagazine.com##.homepagepremedtargetwrapper phonebook.com.pk##.homeposter herold.at##.homesponsor nationalreview.com##.homie_storydiv inaruto.net##.honey-out hoovers.com##.hoov_goog limelinx.com##.horLrgBanner search.yahoo.com##.horiz esecurityplanet.com##.horiz-banner lushstories.com##.horizhide hilarious-pictures.com,soft32.com##.horizontal forlocations.com##.horizontalBanner afro.com##.horizontalBanners ytmnd.com##.horizontal_aids horror.break.com##.horror-ad horror.break.com##.horror-adlabel hotscripts.com##.hostedBy loaded.co.uk##.hot_banner_mpu maps.google.com##.hotel-partner-item-sponsored maps.google.com##.hotel-price zdnet.com##.hotspot europeancarweb.com##.hp-leadertop rte.ie##.hp-mpu huffingtonpost.com##.hp-ss-leaderboard worldweatheronline.com##.hp_300x250_left worldweatheronline.com##.hp_300x250_right surfline.com##.hp_camofday-ad itp.net##.hpbanner nairaland.com##.hpl nairaland.com##.hpr v3.co.uk##.hpu nairaland.com##.hrad blog.recruitifi.com##.hs-cta-wrapper filetram.com##.hsDownload usatodayhss.com##.hss-background-link sfgate.com##.hst-leaderboard chron.com,mysanantonio.com,seattlepi.com,sfgate.com##.hst-siteheader > .row1 ctpost.com##.hst-topclassifieds seattlepi.com##.hst-travelzoo chron.com,mysanantonio.com##.hst-ysm rarlab.com##.htbar + .tplain + table[width="100%"][border="0"] + table[width="100%"][border="0"] pcmag.com##.htmlModule channelinsider.com##.html_module vertor.com##.http helpwithsmoking.com##.hws animenewsnetwork.com##.iab break.com##.iab-300x250 break.com##.iab-label bastropenterprise.com##.iabMedRectContainer tripadvisor.com##.iab_medRec whattoexpect.com##.iabicon infobetting.com##.ibBanner coolest-gadgets.com##.iboxmiddle fileserve.com##.ico_mcLogo bitsnoop.com##.icon + a + div[style="float:right"]:last-child shockwave.com##.icon16AdChoices nme.com##.icon_amazon thebull.com.au##.iconos caughtonset.com##.idlads_widget indianexpress.com##.ie2013-topad heraldsun.com.au##.iframe-316x460 girlsgogames.com##.iframeHolder cnet.com##.iframeWrap worldstarhiphop.com##.iframe[style="height:285px;overflow:hidden;vertical-align:top;"] torrentfusion.com##.iframenull ihavenet.com##.ihn-ad-1 ihavenet.com##.ihn-ad-2 ihavenet.com##.ihn-ad-3 impactlab.net##.ilad filetram.com##.ilividDownload intomobile.com##.im_970x90 sen.com##.image_caption_div imgfave.com##.image_login_message gifsoup.com##.imagead globalgrind.com##.imagecache-article_images_540 blessthisstuff.com##.imagem_sponsor laineygossip.com##.img-box newsbtc.com##.img-responsive weather.msn.com##.imglink1.cf exchangerates.org.uk##.imt4 computerworld.com,infoworld.com##.imu popdust.com##.in politico.com##.in-story-banner networkworld.com##.incontent_ata autoline-eu.co.uk,autoline-eu.co.za,autoline-eu.ie,autoline.info##.index-center-banners-1 socialitelife.com##.index-inser autoline-eu.co.uk,autoline-eu.co.za,autoline-eu.ie,autoline.info##.index-main-banners youplay.com##.index-medium-rectangle abcnews.go.com##.index-quigo autoline-eu.co.uk,autoline-eu.co.za,autoline-eu.ie,autoline.info##.index-secondary-banners vaughnlive.tv##.indexContentRight vosizneias.com##.index_02_perms elivetv.in,torrentz.me##.info cnet.com##.infoboardWrap mp3boo.com##.infolinks tvguide.com##.infomercial easybib.com##.inline-help[href="/reference/help/page/ads"] 4kq.com.au,961.com.au,973fm.com.au,cruise1323.com.au,gold1043.com.au,mix1011.com.au,mix1023.com.au,mix106.com.au,mix1065.com.au,tmz.com,wsfm.com.au##.inline-promo newsweek.com##.inline-promo-link pixdaus.com##.inlineBanner torrentfusion.com##.innards[style="padding-top: 15px;"] brightsideofnews.com##.inner-banner-72890 cartoonnetwork.com##.inner266 medical-hypotheses.com##.innerBanner cnet.com##.innerMPUwrap telegraph.co.uk##.innerPlugin bloggerthemes.net##.inner_banner routes-news.com##.insightbar icanhascheezburger.com##.instream ratemyteachers.com##.intelius itweb.co.za##.intelli-box egmnow.com##.inter_vid bullz-eye.com##.internal_rn_plug_block gizmodo.co.uk##.interruptor ozy.com##.interstitial komando.com##.interstitial-wrapper 12ozprophet.com##.intro jango.com##.intro_block_module:last-child picapp.com##.ipad_300_250 picapp.com##.ipad_728_90 investorplace.com##.ipm-sidebar-ad-text twitter.com##.is-promoted telegraph.co.uk##.isaSeason veehd.com##.isad drivearcade.com,freegamesinc.com##.isk180 abovethelaw.com,dealbreaker.com,itwire.com##.island nzgamer.com##.island-holder timesofisrael.com##.item-spotlight classifiedads.com##.itemhispon classifiedads.com##.itemlospon videopremium.tv##.itrack air1.com,juicefm.com,pulse1.co.uk,pulse2.co.uk,signal1.co.uk,signal2.co.uk,swanseasound.co.uk,thecurrent.org,thewave.co.uk,three.fm,wave965.com,wirefm.com,wishfm.net##.itunes liquidcompass.net##.itunes_btn ixigo.com##.ixi-ads-header liveleak.com##.j_b liveleak.com##.j_t careerone.com.au##.job-search-tower-ad allthingsd.com##.jobs-module bnd.com##.jobs_widget_large ninemsn.com.au##.jobsearchBox toorgle.net##.join mixcloud.com##.js-dfp-mpu careerbuilder.com##.jsHomeSpotBanner deadspin.com,gawker.com,gizmodo.com,io9.com,jalopnik.com,jezebel.com,kotaku.com,lifehacker.com##.js_promoted worldofgnome.org##.jumbotron marketingvox.com##.jupitermedia joomlarulez.com##.jwplayer2 joomlarulez.com##.jwplayer4 rocvideo.tv##.jwpreview sfgate.com##.kaango news24.com##.kalahari_product news24.com##.kalwidgetcontainer imgism.com##.kevin-lb alarabiya.net##.killer mbc.net##.killerbanner vivastreet.co.uk##.kiwii-box-300x250 techspot.com##.konafilter herold.at##.kronehit businessinsider.com##.ks-recommended lenteng.com##.ktz-bannerhead lenteng.com##.ktz_banner anilinkz.tv##.kwarta simplyhired.com##.label_right wallstcheatsheet.com##.landingad8 ustream.tv##.largeRectBanner search.yahoo.com##.last > div[class][data-bid] > div[class] > ul[class] > li > span > a txfm.ie##.last_10Buy afterdawn.com##.last_forum_mainos restaurants.com##.latad espn.co.uk,espncricinfo.com##.latest_sports630 aniscartujo.com##.layer_main iwradio.co.uk##.layerslider_widget thehits.co.nz##.layout__background pastebin.com##.layout_clear milesplit.com##.lb etonline.com##.lb_bottom door2windows.com##.lbad thehill.com##.lbanner speedtest.net##.lbc lankabusinessonline.com##.lbo-ad-home-300x250 itp.net##.lboard pcmag.com##.lbwidget politifact.com##.ldrbd hotscripts.com,scriptcopy.com,techrepublic.com,theatermania.com,thegameslist.com,thepcguild.com##.leader divamag.co.uk,pc-specs.com,readmetro.com##.leader-board interaksyon.com##.leader-board-1 canada.com##.leader-board-wrapper zdnet.com##.leader-bottom online-literature.com##.leader-wrap-bottom online-literature.com##.leader-wrap-middle online-literature.com##.leader-wrap-top garfield.com##.leaderBackground channeleye.co.uk,expertreviews.co.uk,mtv.com.lb,nymag.com,pcpro.co.uk,vogue.co.uk##.leaderBoard greatergood.com##.leaderBoard-container businessghana.com##.leaderBoardBorder whathifi.com##.leaderBoardWrapper expertreviews.co.uk##.leaderLeft expertreviews.co.uk##.leaderRight bakercityherald.com##.leaderTop freelanceswitch.com,stockvault.net,tutsplus.com##.leader_board abovethelaw.com,adn.com,advosports.com,adyou.me,androidfirmwares.net,answerology.com,aroundosceola.com,ballstatedaily.com,bellinghamherald.com,birdmanstunna.com,blitzcorner.com,bnd.com,bradenton.com,cantbeunseen.com,carynews.com,centredaily.com,chairmanlol.com,citymetric.com,claytonnewsstar.com,clgaming.net,clicktogive.com,cnet.com,cokeandpopcorn.com,commercialappeal.com,cosmopolitan.co.uk,cosmopolitan.com,courierpress.com,cprogramming.com,dailynews.co.zw,designtaxi.com,digitaltrends.com,diply.com,directupload.net,dispatch.com,diyfail.com,docspot.com,donchavez.com,driving.ca,dummies.com,edmunds.com,elle.com,enquirerherald.com,esquire.com,explainthisimage.com,expressandstar.com,film.com,foodista.com,fortmilltimes.com,forums.thefashionspot.com,fox.com.au,fresnobee.com,funnyexam.com,funnytipjars.com,galatta.com,gamesville.com,geek.com,goal.com,goldenpages.be,gosanangelo.com,guernseypress.com,hardware.info,heraldonline.com,hi-mag.com,hourdetroit.com,hypegames.com,iamdisappoint.com,idahostatesman.com,imedicalapps.com,independentmail.com,intomobile.com,irishexaminer.com,islandpacket.com,itproportal.com,japanisweird.com,jdpower.com,jerseyeveningpost.com,kentucky.com,keysnet.com,kidspot.com.au,kitsapsun.com,knoxnews.com,lakewyliepilot.com,laweekly.com,ledger-enquirer.com,lgbtqnation.com,lightreading.com,lolhome.com,lonelyplanet.com,lsjournal.com,mac-forums.com,macon.com,mapcarta.com,marieclaire.com,marinmagazine.com,mcclatchydc.com,mercedsunstar.com,meteovista.co.uk,meteovista.com,modbee.com,morefailat11.com,myrtlebeachonline.com,nameberry.com,naplesnews.com,nature.com,nbl.com.au,newsobserver.com,nowtoronto.com,objectiface.com,openfile.ca,organizedwisdom.com,overclockers.com,passedoutphotos.com,pehub.com,peoplespharmacy.com,perfectlytimedphotos.com,photographyblog.com,pinknews.co,pinknews.co.uk,pons.com,pons.eu,popularmechanics.com,pressherald.com,radiobroadcaster.org,rebubbled.com,recode.net,redding.com,reporternews.com,roadandtrack.com,roadrunner.com,roulettereactions.com,rr.com,sacarfan.co.za,sanluisobispo.com,scifinow.co.uk,searchenginesuggestions.com,shinyshiny.tv,shitbrix.com,shocktillyoudrop.com,shropshirestar.com,slashdot.org,slideshare.net,spacecast.com,sparesomelol.com,spoiledphotos.com,sportsvite.com,stopdroplol.com,stripes.com,stv.tv,sunherald.com,supersport.com,tattoofailure.com,tbreak.com,tcpalm.com,techdigest.tv,terra.com,theatermania.com,thehollywoodgossip.com,thejewishnews.com,thenewstribune.com,theolympian.com,theskanner.com,thestate.com,timescolonist.com,timesrecordnews.com,titantv.com,treehugger.com,tri-cityherald.com,tvfanatic.com,uswitch.com,v3.co.uk,vcstar.com,vivastreet.co.uk,vr-zone.com,walyou.com,washingtonpost.com,whatsonstage.com,where.ca,yodawgpics.com,yoimaletyoufinish.com##.leaderboard ameinfo.com##.leaderboard-area autotrader.co.uk,mixcloud.com##.leaderboard-banner bleedingcool.com##.leaderboard-below-header fanlala.com,stltoday.com##.leaderboard-bottom investorwords.com##.leaderboard-box app.com,argusleader.com,battlecreekenquirer.com,baxterbulletin.com,bucyrustelegraphforum.com,burlingtonfreepress.com,centralohio.com,chillicothegazette.com,cincinnati.com,citizen-times.com,clarionledger.com,coloradoan.com,coshoctontribune.com,courier-journal.com,courierpostonline.com,dailyrecord.com,dailyworld.com,defensenews.com,delawareonline.com,delmarvanow.com,democratandchronicle.com,desmoinesregister.com,detroitnews.com,dnj.com,explosm.net,farmanddairy.com,fdlreporter.com,federaltimes.com,freep.com,greatfallstribune.com,greenbaypressgazette.com,greenvilleonline.com,guampdn.com,hattiesburgamerican.com,hometownlife.com,honoluluadvertiser.com,htrnews.com,indystar.com,jacksonsun.com,jconline.com,lancastereaglegazette.com,lansingstatejournal.com,livingstondaily.com,lohud.com,mansfieldnewsjournal.com,marionstar.com,marshfieldnewsherald.com,montgomeryadvertiser.com,mousebreaker.com,mycentraljersey.com,mydesert.com,newarkadvocate.com,news-leader.com,news-press.com,newsleader.com,pal-item.com,pnj.com,portclintonnewsherald.com,postcrescent.com,poughkeepsiejournal.com,press-citizen.com,pressandjournal.co.uk,pressconnects.com,rgj.com,sctimes.com,sheboyganpress.com,shreveporttimes.com,stargazette.com,statesmanjournal.com,stevenspointjournal.com,tallahassee.com,tennessean.com,theadvertiser.com,thecalifornian.com,thedailyjournal.com,theithacajournal.com,theleafchronicle.com,thenews-messenger.com,thenewsstar.com,thenorthwestern.com,thespectrum.com,thestarpress.com,thetimesherald.com,thetowntalk.com,visaliatimesdelta.com,wausaudailyherald.com,wisconsinrapidstribune.com,zanesvilletimesrecorder.com##.leaderboard-container ap.org,app.com,argusleader.com,battlecreekenquirer.com,baxterbulletin.com,bucyrustelegraphforum.com,burlingtonfreepress.com,centralohio.com,chillicothegazette.com,cincinnati.com,citizen-times.com,clarionledger.com,coloradoan.com,coshoctontribune.com,courier-journal.com,courierpostonline.com,dailyrecord.com,dailyworld.com,defensenews.com,delawareonline.com,delmarvanow.com,democratandchronicle.com,desmoinesregister.com,detroitnews.com,dnj.com,fdlreporter.com,federaltimes.com,floridatoday.com,freep.com,greatfallstribune.com,greenbaypressgazette.com,greenvilleonline.com,guampdn.com,hattiesburgamerican.com,hometownlife.com,honoluluadvertiser.com,htrnews.com,indystar.com,jacksonsun.com,jconline.com,lancastereaglegazette.com,lansingstatejournal.com,livingstondaily.com,lohud.com,mansfieldnewsjournal.com,marionstar.com,marshfieldnewsherald.com,montgomeryadvertiser.com,mycentraljersey.com,mydesert.com,newarkadvocate.com,news-leader.com,news-press.com,newsleader.com,pal-item.com,pnj.com,portclintonnewsherald.com,postcrescent.com,poughkeepsiejournal.com,press-citizen.com,pressconnects.com,rgj.com,sctimes.com,sheboyganpress.com,shreveporttimes.com,stargazette.com,statesmanjournal.com,stevenspointjournal.com,tallahassee.com,tennessean.com,theadvertiser.com,thecalifornian.com,thedailyjournal.com,theithacajournal.com,theleafchronicle.com,thenews-messenger.com,thenewsstar.com,thenorthwestern.com,thespectrum.com,thestarpress.com,thetimesherald.com,thetowntalk.com,visaliatimesdelta.com,wausaudailyherald.com,wisconsinrapidstribune.com,zanesvilletimesrecorder.com##.leaderboard-container-top cntraveller.com##.leaderboard-new businessdictionary.com##.leaderboard-placement slideshare.net##.leaderboard-profile geekosystem.com,styleite.com,themarysue.com##.leaderboard-section timesunion.com##.leaderboard-tbl fanlala.com,tvline.com##.leaderboard-top ehow.co.uk,scotsman.com,skysports.com##.leaderboard-wrap ctv.ca##.leaderboard-wrapper whatismybrowser.com##.leaderboard720 english.gazzetta.it##.leaderboardEng cargurus.com##.leaderboardParent japantoday.com##.leaderboard_banner bestcovery.com##.leaderboard_block vibevixen.com##.leaderboard_bottom lookbook.nu,todaysbigthing.com##.leaderboard_container tucsoncitizen.com##.leaderboard_container_top directupload.net##.leaderboard_rectangle porttechnology.org,realworldtech.com,rottentomatoes.com##.leaderboard_wrapper entrepreneur.com.ph##.leaderboardbar ubergizmo.com,wired.co.uk##.leaderboardcontainer fog24.com,free-games.net##.leaderboardholder cherokeetribune.com##.leaderboards theprospectordaily.com##.leaderboardwrap autoevolution.com##.leaderheight morewords.com##.lef youserials.com##.left washingtonjewishweek.com##.left-banner republicbroadcasting.org##.left-sidebar-padder > #text-3 republicbroadcasting.org##.left-sidebar-padder > #text-8 elliotsblog.com##.left.box routes-news.com##.left1 israelnationalnews.com##.leftColumn ask.com##.leftLabel bargaineering.com##.leftSidebar yellowpages.com.ps##.leftSponsors prevention.com##.leftSubBoxArea 10minutemail.net##.leftXL mixfmradio.com##.left_2_banners2 indiaresults.com##.left_add_incl ultimate-guitar.com##.left_article_cont electronista.com,ipodnn.com,macnn.com##.left_footer zalaa.com##.left_iframe mail.yahoo.com##.left_mb wnd.com##.left_prom_160 youserials.com##.lefta torrentreactor.net##.leftbanner knowthis.com##.leftcol[style="width:180px;"] jta.org##.letter-to-editor miniclip.com##.letterbox jpost.com##.level-2-horizontal-banner-wrap jpost.com##.level-6-horizontal-banner-wrap aol.com##.lft120x60 webpronews.com##.lightgray prepperwebsite.com##.link-col > #text-48 coinurl.com##.link-image anorak.co.uk##.link[style="height: 250px"] huffingtonpost.com##.linked_sponsored_entry technologyreview.com##.linkexperts-hm kyivpost.com##.linklist kproxy.com##.linknew4 scriptcopy.com##.linkroll scriptcopy.com##.linkroll-title babynamegenie.com,forless.com,o2cinemas.com,worldtimeserver.com##.links atđhe.net##.links > thead answers.com##.links_google answers.com##.links_openx ipsnews.net##.linksmoll_black watchseries.lt##.linktable > .myTable > tbody > tr:first-child youtube.com##.list-view[style="margin: 7px 0pt;"] maps.yahoo.com##.listing > .ysm cfos.de##.ll_center pcworld.idg.com.au##.lo-toppromos wefollow.com##.load-featured calgaryherald.com##.local-branding theonion.com##.local_recirc logect.com##.logect_ads01_wrp tv-video.net##.login wearetennis.com##.logo siberiantimes.com##.logoBanner ovguide.com##.logo_affiliate themoscowtimes.com##.logo_popup toblender.com##.longadd vg247.com##.low-leader-container eurogamer.net##.low-leaderboard-container omegle.com##.lowergaybtn omegle.com##.lowersexybtn cfos.de##.lr_left yahoo.com##.lrec findlaw.com##.ls_homepage animetake.com##.lsidebar > a[href^="http://bit.ly/"] vidto.me,vidzi.tv##.ltas_backscreen phpbb.com##.lynkorama phpbb.com##.lynkoramaz kovideo.net##.lyricRingtoneLink readwrite.com##.m-adaptive theverge.com##.m-feature__intro > aside digitaltrends.com##.m-intermission digitaltrends.com##.m-leaderboard theguardian.com##.m-money-deals digitaltrends.com##.m-review-affiliate-pint tvguide.com##.m-shop share-links.biz##.m10.center share-links.biz##.m20 > div[id]:first-child:last-child minivannews.com##.m_banner_show downloadatoz.com##.ma movies.msn.com##.magAd christianpost.com##.main-aside-bn thedailystar.net##.mainAddSpage investing.com##.mainLightBoxFilter instantshift.com##.main_banner_single technewsdaily.com##.main_content_right israelhayom.com##.main_english_banner electronista.com##.main_notify investopedia.com##.mainbodyleftcolumntrade xspyz.com##.mainparagraph showme.co.za##.mainphoto healthzone.pk##.maintablebody rarlab.com,rarlabs.com##.maintd2[valign="top"] > .htbar:first-child + .tplain + p + table[width="100%"][border="0"] + table[width="100%"][border="0"] > tbody:first-child:last-child rarlabs.com##.maintd2[valign="top"] > .htbar:first-child + p.tplain + table[width="100%"][border="0"] + table[width="100%"][border="0"] lifescript.com##.maintopad torrent.cd##.maintopb makeprojects.com##.makeBlocks 4shared.com##.makeRingtoneButton mangainn.com##.mangareadtopad allmenus.com##.mantle sigalert.com##.map-med-rect rocvideo.tv##.mar-bot-10 pcper.com##.mark-overlay-bg briefing.com##.market-place industryweek.com##.market600 nzherald.co.nz##.marketPlace knowd.com,rockpapershotgun.com,theslingshot.com##.marketing bangkok.com##.marketing-spot investmentweek.co.uk##.marketing_content digitalspy.co.uk##.marketing_puff abc15.com,abc2news.com,barchart.com,entrepreneur.com,globest.com,industryweek.com,kypost.com,livescience.com,myfoxatlanta.com,myfoxboston.com,myfoxchicago.com,myfoxdc.com,myfoxdetroit.com,myfoxhouston.com,myfoxla.com,myfoxmemphis.com,myfoxny.com,myfoxphilly.com,myfoxphoenix.com,myfoxtampabay.com,newsarama.com,newsnet5.com,wcpo.com,wptv.com,wxyz.com,yahoo.com##.marketplace poststar.com,stltoday.com##.marketplace-list dailymotion.com##.masscast_box dailymotion.com##.masscast_middle_box macworld.co.uk##.mastBannerContainer mp3juices.com##.master_search_table > tbody > .c[style="height:80px"]:first-child songlyrics.com##.masthead slacktory.com##.masthead-banner msn.com##.matchModuleContainer fixitscripts.com##.max-banner mail.yahoo.com##.mb > .tbl commentarymagazine.com##.mb5px yahoo.com##.mballads zeetv.com##.mbanner1 wraltechwire.com##.mbitalic search.twcc.com##.mbs games.yahoo.com,movies.yahoo.com##.md.links wsj.com##.mdcSponsorBadges hughhewitt.com##.mdh-main-wrap mtv.com##.mdl_noPosition thestar.com.my##.med-rec indianapublicmedia.org##.med-rect slideshare.net##.medRecBottom2 orlandoweekly.com##.medRectangle etonline.com##.med_rec medcitynews.com##.medcity-paid-inline fontstock.net##.mediaBox tvbay.org##.mediasrojas tvplus.co.za##.medihelp-section docspot.com##.medium allmusic.com,edmunds.com##.medium-rectangle monhyip.net##.medium_banner ucomparehealthcare.com##.medium_rectangle beautifuldecay.com##.medium_rectangle_300x250 rushlimbaugh.com##.mediumrec_int democraticunderground.com##.mediumrectangle-op-blank democraticunderground.com##.mediumrectangle-placeholder 9news.com.au,active.com,anime-planet.com,cookinggames.com,coolgames.com,fosswire.com,girlgames.com,girlsocool.com,guygames.com,hallpass.com,stickgames.com,tinypic.com,tuaw.com,watchmojo.com##.medrec active.com##.medrec-bottom dressupgal.com##.medrec-main active.com##.medrec-top myspace.com##.medrecContainer rottentomatoes.com##.medrec_top_wrapper joystiq.com,luxist.com,switched.com,tuaw.com,wow.com##.medrect theboot.com##.medrect_aol notcot.org##.medrect_outer gossiponthis.com##.medrectangle ludobox.com##.megaban lookbook.nu##.megabanner_container gamerdna.com##.members deseretnews.com##.menu-sponsor toonjokes.com##.menu_fill_ad flysat.com##.menualtireklam spinitron.com##.merch muzu.tv##.merchandise travelocity.com##.merchandising excite.com##.mexContentBdr moviefone.com##.mf-banner-container moviefone.com##.mf-tower600-container seenive.com##.mgid-vine moviesplanet.com##.mgtie5min modernhealthcare.com##.mh_topshade_b npr.org##.mi-purchase-links slate.com##.microsoft_text_link krebsonsecurity.com##.mid-banner pissedconsumer.com,plussports.com##.midBanner investing.com##.midHeader expertreviews.co.uk##.midLeader siteadvisor.com##.midPageSmallOuterDiv autotrader.co.za##.midSearch.banner mp3.li##.mid_holder[style="height: 124px;"] einthusan.com##.mid_leaderboard einthusan.com##.mid_medium_leaderboard babylon.com##.mid_right einthusan.com##.mid_small_leaderboard metroflog.com##.midbanner scanwith.com##.middle-banner ibtimes.co.in,ibtimes.co.uk##.middle-leaderboard imdb.com##.middle-rhs instantshift.com##.middle_banners_title kcrw.com##.middle_bottom_wrap mamma.com##.midresult:first-child broadcastingworld.net##.midsection tokyohive.com##.midunit rapidlibrary.com##.mini.mediaget ar15.com##.miniBannersBg fool.com##.mintPromo independent.co.uk,standard.co.uk##.mktg-btns-ctr aol.com##.mlid-netbanner mmosite.com##.mmo_banner mmosite.com##.mmo_footer_sponsor mmosite.com##.mmo_gg mmosite.com##.mmo_gg2 mmosite.com##.mmo_textsponsor androidcentral.com##.mn-banner mnn.com##.mnn-homepage-adv1-block cultofmac.com##.mob-mpu techradar.com##.mobile-hawk-widget techspot.com##.mobile-hide rapidvideo.tv##.mobile_hd thenation.com##.modalContainer ibtimes.com##.modalDialog_contentDiv_shadow ibtimes.com##.modalDialog_transparentDivs thenation.com##.modalOverlay alivetorrents.com##.mode itworld.com##.module goal.com##.module-bet-signup goal.com##.module-bet-windrawwin autotrader.co.uk##.module-ecommerceLinks kiis1065.com.au##.module-mrec nickelodeon.com.au##.module-mrect heraldsun.com.au##.module-promo-image-01 wptv.com##.module.horizontal asia.cnet.com##.module:first-child + .module hubpages.com##.moduleAmazon quote.com##.module_full prevention.com##.modules americantowns.com##.moduletable-banner healthyplace.com##.moduletablefloatRight uberrock.co.uk##.moduletablepatches codeasily.com##.money theguardian.com##.money-supermarket dailymail.co.uk,mailonsunday.co.uk,thisismoney.co.uk##.money.item > .cmicons.cleared.bogr3.link-box.linkro-darkred.cnr5 au.news.yahoo.com##.moneyhound yahoo.com##.more-sponsors motherboard.tv##.moreFromVice aol.co.uk##.moreOnAsylum bestserials.com##.morePop search.icq.com##.more_sp search.icq.com##.more_sp_end zillow.com##.mortgage-featured-partners radiosport.co.nz##.mos-sponsor anonymouse.org##.mouselayer merdb.com##.movie_version a[style="font-size:15px;"] movie2k.tl##.moviedescription + br + div > a putlocker.is##.movsblu seetickets.com##.mp-sidebar-right newscientist.com##.mpMPU bakersfieldnow.com,katu.com,keprtv.com,komonews.com,kpic.com,kval.com,star1015.com##.mpsponsor 98fm.com,accringtonobserver.co.uk,alloaadvertiser.com,ardrossanherald.com,audioreview.com,autotrader.co.za,barrheadnews.com,bigtop40.com,birminghammail.co.uk,birminghampost.co.uk,bizarremag.com,bobfm.co.uk,bordertelegraph.com,bracknellnews.co.uk,capitalfm.com,capitalxtra.com,carrickherald.com,caughtoffside.com,centralfifetimes.com,chesterchronicle.co.uk,chroniclelive.co.uk,classicfm.com,clydebankpost.co.uk,computerworlduk.com,coventrytelegraph.net,crewechronicle.co.uk,cultofandroid.com,cumnockchronicle.com,dailypost.co.uk,dailyrecord.co.uk,dcsuk.info,directory.im,divamag.co.uk,dumbartonreporter.co.uk,dunfermlinepress.com,durhamtimes.co.uk,eastlothiancourier.com,econsultancy.com,examiner.co.uk,findanyfilm.com,gardensillustrated.com,gazettelive.co.uk,getbucks.co.uk,getreading.co.uk,getsurrey.co.uk,getwestlondon.co.uk,golf365.com,greenocktelegraph.co.uk,heart.co.uk,helensburghadvertiser.co.uk,her.ie,herfamily.ie,impartialreporter.com,independent.co.uk,irishexaminer.com,irvinetimes.com,jamieoliver.com,joe.co.uk,joe.ie,journallive.co.uk,largsandmillportnews.com,liverpoolecho.co.uk,localberkshire.co.uk,loughboroughecho.net,macclesfield-express.co.uk,macuser.co.uk,manchestereveningnews.co.uk,metoffice.gov.uk,mtv.com.lb,mumsnet.com,musicradar.com,musicradio.com,mygoldmusic.co.uk,newburyandthatchamchronicle.co.uk,newstalk.com,northernfarmer.co.uk,osadvertiser.co.uk,peeblesshirenews.com,pinknews.co.uk,propertynews.com,racecar-engineering.com,radiotimes.com,readingchronicle.co.uk,realradioxs.co.uk,recombu.com,redhillandreigatelife.co.uk,rochdaleonline.co.uk,rossendalefreepress.co.uk,runcornandwidnesweeklynews.co.uk,scotsman.com,skysports.com,sloughobserver.co.uk,smallholder.co.uk,smartertravel.com,smoothradio.com,southportvisiter.co.uk,southwestfarmer.co.uk,spin1038.com,spinsouthwest.com,sportsjoe.ie,strathallantimes.co.uk,t3.com,tcmuk.tv,the-gazette.co.uk,theadvertiserseries.co.uk,thecitizen.co.tz,thejournal.co.uk,thelancasterandmorecambecitizen.co.uk,thetimes.co.uk,thevillager.co.uk,timeoutabudhabi.com,timeoutbahrain.com,timeoutdoha.com,timeoutdubai.com,todayfm.com,toffeeweb.com,troontimes.com,tv3.ie,txfm.ie,walesonline.co.uk,warringtonguardian.co.uk,wiltshirebusinessonline.co.uk,windsorobserver.co.uk,xfm.co.uk##.mpu greatbritishlife.co.uk,sport360.com##.mpu-banner 4music.com##.mpu-block rightmove.co.uk##.mpu-slot muzu.tv##.mpu-wrap crash.net##.mpuBack digitalartsonline.co.uk##.mpuHolder lonelyplanet.com##.mpuWrapper slidetoplay.com##.mpu_content_banner popjustice.com##.mpufloatleft blinkbox.com##.mpupnl digitimes.com##.mr-box 411.com##.mr_top 2gb.com,9news.com.au,ebay.com,farmonline.com.au,farmweekly.com.au,fhm.com.ph,foodnetwork.com,funnyordie.com,goodfruitandvegetables.com.au,hgtv.com,hgtvremodels.com,jozifm.co.za,metrofm.co.za,northqueenslandregister.com.au,queenslandcountrylife.com.au,realliving.com.ph,stockandland.com.au,stockjournal.com.au,theland.com.au,thewest.com.au,topgear.com.ph,turfcraft.com.au##.mrec yellowpages.com.au##.mrec-container pep.ph##.mrec-wrapper plus.im##.ms-creative-position-header manilastandardtoday.com##.mst-banner manilastandardtoday.com##.mst-banner-sidebar govtech.com##.mt-20 motortrend.com##.mt-spotlight facemoods.com##.mts + .search-list facebook.com##.muffin.group excite.co.uk##.multitable javascript-coder.com##.myadv1 mycoupons.com##.myc_google slate.com##.mys-header slate.com##.mys-north-spons-ad google.com##.nH.MC mail.google.com##.nH.PS mail.google.com##.nH.adC > .nH > .nH > .u5 > .azN manchesterconfidential.co.uk##.nag bbc.com##.native-promo-button 9gag.com##.naughty-box animenfo.com##.nav2 btstorrent.so##.nav_bar + p[style="margin:4px 0 10px 10px;font-size:14px;width:auto;padding:2px 50px 2px 50px;display:inline-block;border:none;border-radius:3px;background:#EBDCAF;color:#BE8714;font-weight:bold;"] + .tor bloodninja.org##.navbar + .container-fluid > .row:first-child > .col-md-2:first-child typo3.org##.navigationbanners nba.com##.nbaSponsored universalsports.com##.nbc_Adv ncaa.com##.ncaa728text ncaa.com##.ncaaAdTag 4shared.com##.ndimg whoismind.com##.neatbox[style="color:#777;width:450px;padding:5px 15px;margin-bottom:10px;line-height:20px;cursor:pointer;"] muzu.tv##.networkLeaderboard depositfiles.com,dfiles.eu##.network_downloader celebritynetworth.com##.networth_content_advert keepcalm-o-matic.co.uk##.new-banner northjersey.com##.newerheaderbg instructables.com##.newrightbar_div_10 jpost.com##.news-feed-banner ckom.com,newstalk650.com##.news-sponsor afterdawn.com##.newsArticleGoogle afterdawn.com##.newsGoogleContainer tech-reviews.co.uk##.newsadsix codingforums.com##.newscredit pbs.org##.newshour-support-wrap develop-online.net,licensing.biz,mcvuk.com,mobile-ent.biz,pcr-online.biz,toynews-online.biz##.newsinsert jpost.com##.newsmax exchangerates.org.uk##.newsp democraticunderground.com##.nhome-mediumrectangle-container hulkshare.com##.nhsBotBan travel.yahoo.com##.niftyoffst[style="background-color: #CECECE; padding: 0px 2px 0px;"] 9news.com.au,ninemsn.com.au##.ninemsn-advert cosmopolitan.com.au,dolly.com.au##.ninemsn-mrec filenuke.com,sharesix.com##.nnrplace smartmoney.com##.no-top-margin thedailycrux.com##.noPrint mtv.co.uk##.node-download androidcentral.com##.node-list-body > .node-sponsoredpost doctoroz.com##.node-site_promo tradingmarkets.com##.node_banner_right thepiratebay.se##.nohover news.com.au##.nokia-short spotplanet.org##.nonregadd moddb.com##.normalmediabox cookingforengineers.com##.nothing primeshare.tv##.notification[style="width:900px; margin-left:-10px;margin-bottom:-1px;"] philly.com##.nouveau financialpost.com##.npBgSponsoredLinks channel4fm.com##.npDownload financialpost.com##.npSponsor financialpost.com,nationalpost.com##.npSponsorLogo nascar.com##.nscrAd nascar.com##.nscrAdFooter nascar.com##.nscrSweepsContainer ninemsn.com.au##.nw_ft_all_partners nymag.com,vulture.com##.nym-ad-active nytimes.com##.nytmm-ss-ad-target nytimes.com##.nytmm-ss-big-ad nzherald.co.nz##.nzh-bigbanner nzherald.co.nz##.nzh-extendedbanner mail.google.com##.oM counton2.com,suntimes.com##.oas adage.com##.oaswrapper dailydot.com##.ob_dual_right elle.com,womansday.com##.oba tvguide.com##.obj-spotlight infobetting.com,searchenginejournal.com##.odd wusa9.com##.ody-ob-taboola-wrapper lifehack.org##.offer yasni.com##.offerbox livescience.com,nationalpost.com,space.com##.offers polishlinux.org##.oio-badge mindsetforsuccess.net##.ois_wrapper okcupid.com##.okad nzbindex.nl##.oldresults somethingawful.com##.oma_pal plus.im##.one-creative 50statesclassifieds.com##.onepxtable[width="468"] thedigeratilife.com##.optad all-shares.com##.outInformation news.sky.com##.outbrain-table-recommendations-bottom jpopasia.com##.overflow-h[style="height:150px;"] eeweb.com,megashare.com##.overlay hqvideo.cc,vidbox.net,vidshare.ws,vuvido.com,xtshare.com,zalaa.com##.overlayVid stream4k.to##.overlay_box search.yahoo.com##.overture getprice.com.au##.overviewnc2_side_mrec facebook.com##.ownsection[role="option"] info.co.uk##.p worldoftanks-wot.com##.p2small local.com##.pB5.mB15 polls.aol.com##.p_divR amazon.com##.pa-sp-container chaptercheats.com,longislandpress.com,tucows.com##.pad10 demonoid.pw##.pad9px_left > table:nth-child(8) inquirer.net##.padtopbot5 xtremevbtalk.com##.page > #collapseobj_rbit hotfrog.ca,hotfrog.com,hotfrog.com.au,hotfrog.com.my##.page-banner channel4.com##.page-bg-link politico.com##.page-skin-graphic channel4.com##.page-top-banner vehix.com##.pageHead krcrtv.com,ktxs.com,nbcmontana.com,wcti12.com,wcyb.com##.pageHeaderRow1 freebetcodes.info##.page_free-bet-codes_1 nzcity.co.nz##.page_skyscraper nationalreview.com##.pagetools[align="center"] optimum.net##.paidResult infoq.com##.paid_section phonebook.com##.paidinfoportlet eplans.com##.pair-bottom-banners womenshealthmag.com##.pane-block-150 bostonherald.com##.pane-block-20 galtime.com##.pane-block-9 sportfishingmag.com##.pane-channel-sponsors-list animax-asia.com,axn-asia.com,betvasia.com,gemtvasia.com,movies4men.co.uk,onetvasia.com,settv.co.za,sonychannel.co.za,sonychannelasia.com,sonymax.co.za,sonymoviechannel.co.uk,sonytv.com##.pane-dart-dart-tag-300x250-rectangle soundandvisionmag.com##.pane-dart-dart-tag-bottom thedrum.com##.pane-dfp thedrum.com##.pane-dfp-drum-mpu-adsense educationpost.com.hk##.pane-dfp-homepage-728x90 texasmonthly.com##.pane-dfp-sidebar-medium-rectangle-1 texasmonthly.com##.pane-dfp-sidebar-medium-rectangle-2 pri.org##.pane-node-field-links-sponsors scmp.com##.pane-scmp-advert-doubleclick 2gb.com##.pane-sponsored-links-2 sensis.com.au##.panel tampabay.com##.panels-flexible-row-75-8 panarmenian.net##.panner_2 nst.com.my##.parargt whatsthescore.com##.parier prolificnotion.co.uk,usatoday.com##.partner investopedia.com##.partner-center mail.com##.partner-container thefrisky.com##.partner-link-boxes-container nationtalk.ca##.partner-slides emporis.com##.partner-small news24.com,timesofisrael.com##.partner-widget domainmasters.co.ke##.partner2 kat.ph##.partner2Button kat.ph##.partner3Button newser.com##.partnerBottomBorder solarmovie.ag,solarmovie.so##.partnerButton bing.com##.partnerLinks newser.com##.partnerLinksText delish.com##.partnerPromoCntr youbeauty.com##.partner_content mamaslatinas.com##.partner_links 411.com##.partner_search_header 411.com##.partner_searches freshnewgames.com##.partnercontent_box money.msn.com##.partnerlogo bhg.com##.partnerpromos 2oceansvibe.com,browardpalmbeach.com,bundesliga.com,citypages.com,computershopper.com,dallasobserver.com,evertonfc.com,freedict.com,houstonpress.com,independent.co.uk,miaminewtimes.com,ocweekly.com,pcmag.com,phoenixnewtimes.com,riverfronttimes.com,tgdaily.com,tweetmeme.com,villagevoice.com,wbj.pl,westword.com,wilv.com##.partners araratadvertiser.com.au,areanews.com.au,armidaleexpress.com.au,avonadvocate.com.au,batemansbaypost.com.au,baysidebulletin.com.au,begadistrictnews.com.au,bellingencourier.com.au,bendigoadvertiser.com.au,blayneychronicle.com.au,bombalatimes.com.au,boorowanewsonline.com.au,bordermail.com.au,braidwoodtimes.com.au,bunburymail.com.au,busseltonmail.com.au,camdencourier.com.au,canowindranews.com.au,centraladvocate.com.au,centralwesterndaily.com.au,cessnockadvertiser.com.au,colliemail.com.au,colypointobserver.com.au,coomaexpress.com.au,cootamundraherald.com.au,cowraguardian.com.au,crookwellgazette.com.au,dailyadvertiser.com.au,dailyliberal.com.au,donnybrookmail.com.au,dungogchronicle.com.au,easternriverinachronicle.com.au,edenmagnet.com.au,esperanceexpress.com.au,forbesadvocate.com.au,gleninnesexaminer.com.au,gloucesteradvocate.com.au,goondiwindiargus.com.au,goulburnpost.com.au,greatlakesadvocate.com.au,grenfellrecord.com.au,guyraargus.com.au,hardenexpress.com.au,hepburnadvocate.com.au,huntervalleynews.net.au,inverelltimes.com.au,irrigator.com.au,juneesoutherncross.com.au,lakesmail.com.au,lithgowmercury.com.au,macleayargus.com.au,mailtimes.com.au,maitlandmercury.com.au,mandurahmail.com.au,manningrivertimes.com.au,margaretrivermail.com.au,merimbulanewsonline.com.au,merredinmercury.com.au,moreechampion.com.au,mudgeeguardian.com.au,muswellbrookchronicle.com.au,myallcoastnota.com.au,nambuccaguardian.com.au,naroomanewsonline.com.au,narrominenewsonline.com.au,newcastlestar.com.au,northerndailyleader.com.au,northweststar.com.au,nvi.com.au,nynganobserver.com.au,oberonreview.com.au,parkeschampionpost.com.au,portnews.com.au,portpirierecorder.com.au,portstephensexaminer.com.au,queanbeyanage.com.au,riverinaleader.com.au,sconeadvocate.com.au,singletonargus.com.au,southcoastregister.com.au,southernhighlandnews.com.au,southernweekly.com.au,standard.net.au,stawelltimes.com.au,summitsun.com.au,tenterfieldstar.com.au,theadvocate.com.au,thecourier.com.au,theherald.com.au,theridgenews.com.au,therural.com.au,townandcountrymagazine.com.au,ulladullatimes.com.au,waginargus.com.au,walchanewsonline.com.au,wauchopegazette.com.au,wellingtontimes.com.au,westernadvocate.com.au,westernmagazine.com.au,winghamchronicle.com.au,yasstribune.com.au,youngwitness.com.au##.partners-container serverwatch.com##.partners_ITs racinguk.com##.partners_carousel_container ryanair.com##.partnersmenu nzbclub.com##.partsincomplete prankvidz.com,videobash.com##.pb-container eeweb.com##.pbox neverendingplaylist.com##.pcad geek.com##.pcmag-mostclicked photodom.com##.pd_AdBlock search.smartaddressbar.com##.peach imvu.com##.peoplesearch-ad forums.vr-zone.com##.perm_announcement politifact.com##.pfad proxfree.com##.pfad2 invisionfree.com##.pformleft[width="300px"] sensis.com.au##.pfpRightParent sensis.com.au##.pfplist proxfree.com##.pftopad mashable.com##.pga roadandtrack.com##.photo-banner phoronix.com##.phxcms_contentphx_right_bar:first-child metacrawler.com,start.mysearchdial.com##.pirArea vr-zone.com##.place_top gamersyde.com##.placeholder-bottom gamersyde.com##.placeholder-top qikr.co##.placeholder1 qikr.co##.placeholder2 autotrader.co.uk##.placeholderBottomLeaderboard autotrader.co.uk##.placeholderTopLeaderboard dummies.com,laweekly.com##.placement world-airport-codes.com##.placement-leaderboard world-airport-codes.com##.placement-mpu world-airport-codes.com##.placement-skyscraper t45ol.com##.play_game_adcube_bloc overthumbs.com##.playerad mediaspanonline.com##.playlist-itunes-player netmums.com##.plinth-mpu ulivetv.com##.plugbarremozi wsj.com##.pmCfoDeloitte streamingthe.net##.pnl_video_2 freewebarcade.com##.pnum pokernewsreport.com##.pokerbanner bodybuilding.com##.poll-padding winnipegfreepress.com##.poll-sponsor filefactory.com##.popup bangbrosporn.com##.porndiddy freenewspos.com##.pos-adt freenewspos.com##.pos-adv monova.org##.pos-download-big blogtv.com##.posAbs.BOGL blogtv.com##.posRel.BGW.BOGL.TxtC.FB.L0 blogtv.com##.posRel.txtL.userForeColor.userBoxBG.BOGL forums.linuxmint.com##.post + .divider + .bg3 macdailynews.com##.post + .link-list fullepisode.info,netbooknews.com##.post-banner activistpost.com##.post-body > div[style="text-align: center;"] > a[target="_blank"] > img activistpost.com##.post-body a[style^="clear: right; float: right; margin-bottom: 1em; "][target="_blank"] > img[alt] motherjones.com##.post-continued-from-above motherjones.com##.post-continues awesomestyles.com##.post-download-screen mobilitydigest.com##.post-rel moviecarpet.com##.post-top pinkisthenewblog.com##.post-wrap buzzfeed.com##.post2[style="background-color: #FDF6E5;"] mac-forums.com##.postMREC thejournal.ie##.postSponsored dutchgrammar.com##.post[style="border: 1px solid #339999 "] wwtdd.com##.post_insert androidpolice.com##.post_main_blob2 litecointalk.org##.post_separator + .windowbg neogaf.com##.postbit-goodie cincinnati.com,wbir.com##.poster-container phonebook.com.pk##.posterplusmiddle phonebook.com.pk##.posterplustop picocool.com##.postgridsingle 1019thewolf.com,923thefox.com,fox1150.com,hot1035radio.com,indie1031.com##.posts-banner firstpost.com##.powBy geekzone.co.nz##.poweredBy infowars.com,prisonplanet.com##.ppani planet-rugby.co.za,planetrugby.com##.pr-art-betlinks lowellsun.com##.preHeaderRegion gamesting.com##.pregleaderboard gcnlive.com##.premSponsor towersearch.com##.premier thomsonlocal.com##.premium yellowbook.com##.premium-listing dramafever.com##.premium-overlay warez-files.com##.premium_results huffingtonpost.com##.presented-by theatlanticwire.com##.presented_by softexia.com##.press-lastest pokerupdate.com##.prev-article 1cookinggames.com,dressupone.com,flobzoo.com,onlyfungames.com,playkissing.com,yokogames.com##.preview2bannerspot 1cookinggames.com##.preview2bannerspot2 onlyfungames.com##.preview3bannerspot dressupone.com##.previewpubgoogle dressupone.com##.previewpubgoogle2 androidbenchmark.net,cpubenchmark.net,harddrivebenchmark.net,iphonebenchmark.net,memorybenchmark.net,videocardbenchmark.net##.price news24.com##.pricecheckBlock digitaltrends.com##.pricegrabber anandtech.com##.pricing vaughnlive.tv##.primary300x600 foliomag.com##.prime_sponsors theguardian.com##.print-sponsorship tulsaworld.com##.printViewAll vertor.com##.privacy_banner toptenreviews.com##.prod_head_buy_button search.yahoo.com##.prod_object barnesandnoble.com##.product-commentary-advertisement avsforum.com##.products openwith.org##.program-link pbs.org##.program-support gokunming.com##.prom wnd.com##.prom-full-width-expandable babynamegenie.com,computerandvideogames.com,dailyrecord.co.uk,eclipse.org,film.com,foreignpolicy.com,irishmirror.ie,manchestereveningnews.co.uk,nbcbayarea.com,networkworld.com,planetsourcecode.com,sandiego6.com,sciagaj.org,thenextweb.com,theonion.com,totalxbox.com,varsity.com,wsj.com##.promo yfrog.com,yt-festivals.appspot.com##.promo-area bbcgoodfood.com,pri.org##.promo-box lamag.com##.promo-container thepeoplesperson.com##.promo-first-para pokertube.com##.promo-holder news.com.au##.promo-image-01 cointelegraph.com##.promo-item efinancialnews.com##.promo-leaderboard sitepoint.com##.promo-panel search.yahoo.com##.promo-res imageshack.com##.promo-right thepeoplesperson.com##.promo-right-300 miniclip.com##.promo-text miniclip.com##.promo-unit cio.com,csoonline.com,infoworld.com,itworld.com,javaworld.com##.promo.list bollywoodhungama.com##.promo266 cnet.com##.promo3000 semoneycontrol.com##.promoBanner downloadcrew.com##.promoBar zdnet.com##.promoBox fitnessmagazine.com##.promoContainer itv.com##.promoMpu kat.ph##.promoPartner gamepedia.com##.promoSidebar mirror.co.uk##.promoTeaser videobb.com##.promo_tab animecharactersdatabase.com##.promobanner journallive.co.uk,liverpooldailypost.co.uk,walesonline.co.uk##.promobottom cnet.com.au,photobucket.com,ratemyteachers.com##.promobox dnainfo.com##.promomerchant_block afullcup.com##.promos penny-arcade.com##.promos-horizontal search.genieo.com,search.installmac.com##.promoted twitter.com##.promoted-account twitter.com##.promoted-trend twitter.com##.promoted-tweet youtube.com##.promoted-videos search.genieo.com##.promoted_right bizcommunity.com##.promotedcontent-box reddit.com##.promotedlink northcountrypublicradio.org##.promotile twitter.com##.promotion yfrog.com##.promotion-side vogue.co.uk##.promotionButtons thenextweb.com##.promotion_frame mademan.com##.promotion_module 951shinefm.com##.promotional-space wired.co.uk##.promotions domainnamewire.com##.promotions_120x240 journallive.co.uk,liverpooldailypost.co.uk,people.co.uk,walesonline.co.uk##.promotop bullz-eye.com##.prompt_link mywebsearch.com##.prontoBox independent.co.uk,standard.co.uk##.propertySearch msn.com##.providerupsell psmag.com##.psmag-ad-300px psmag.com##.psmag-ad-300x250 playswitch.com##.psmainshellad dailyhome.com##.pt1_pane_body[style="text-align:center;height:90px;"] annistonstar.com##.pt1_pane_body[style="text-align:left;height:90px;"] essentialmums.co.nz##.ptbl 1980-games.com,flash-mp3-player.net,theportugalnews.com##.pub euronews.com##.pub-block tvgolo.com##.pub468x60top catchvideo.net##.pubRight catchvideo.net##.pubTop radionomy.com##.pub_imu videolan.org##.pub_text hellokids.com##.pub_topright elpais.com##.publi220_elpais elpais.com##.publi300_elpais elpais.com##.publi728_elpais hotshare.net,supershare.net##.publi_videos1 reporter.bz##.publicidad-logo europolitics.info##.publicite1 cinemalebnen.org##.publicity protect-url.net##.pubpagebas journallive.co.uk,liverpooldailypost.co.uk##.puffs coinwarz.com##.pull-left[style="margin-right: 30px; margin-top: 20px; width: 336px;\a height: 280px;"] radio.com##.purchase m.facebook.com,touch.facebook.com##.pyml torfinder.net##.q2 qrobe.it##.qad torfinder.net##.qh22 tmz.com##.quigo-main tmz.com##.quigo-permalink moviefone.com##.quigoModule modernghana.com##.quikr_banner israbox.com##.quote > center > table[width="100%"]:first-child unlockboot.com##.r-banner search.icq.com##.r2-1 decoist.com##.r300 periscopepost.com##.r72890 contactmusic.com##.rCol joins.com,rt.com##.r_banner dietsinreview.com##.r_content_300x250 wahm.com##.rad-links wired.com##.rad-top dawn.com##.radWrapper kvcr.org##.radio_livesupport about.com##.radlinks mygames4girls.com##.rads07 dailyfreegames.com##.radsbox weatherzone.com.au##.rainbowstrip nairaland.com##.ratatamp isearch.whitesmoke.com##.rating amctv.com##.rb-dart bustedcoverage.com##.rcr-box wsj.com##.reTransWidget elyrics.net##.read3 infoworld.com##.recRes_head ebookee.org##.recomended webopedia.com##.recommend si.com##.recommend-section biblegateway.com##.recommendations wallpapers-room.com##.recommendations-468x60 biblegateway.com##.recommendations-column biblegateway.com##.recommendations-header-column biblegateway.com##.recommendations-view-row alternet.org,exactseek.com##.recommended vertor.com##.recommended_clients xml.com##.recommended_div2 gsmchoice.com##.recommends uinterview.com##.rect-min-height dailynews.co.zw,defenseindustrydaily.com,dosgamesarchive.com,sciencedaily.com,twogag.com,webappers.com##.rectangle wdun.com##.rectangle-300x250px geekologie.com##.rectangle-container geekosystem.com,styleite.com,themarysue.com##.rectangle-section scholastic.com##.rectangleMedium games.co.uk,gamesgames.com##.rectangular-banners girlsgogames.com##.rectbanner girlsgogames.com##.rectbanner-container whatdigitalcamera.com##.reevoo reviewjournal.com##.region-content_bottom nbcolympics.com##.region-leaderboard examiner.com##.region-masthead ana-white.com##.region-sidebar-second > #block-block-64 extrahardware.com##.region-skyscraper freshwap.net##.regular futbol24.com##.rek topclassifieds.info##.reklama_vip radiosi.eu##.reklame appleinsider.com##.rel-half-r-cnt-ad israbox.com,sedoparking.com,techeblog.com##.related pokerupdate.com##.related-room classifiedextra.ca##.relativeBandeau classifiedextra.ca##.relativeBoite sleepywood.net##.relstar ixquick.com##.reltext cghub.com##.remove_ads forums.whirlpool.net.au##.reply[style="padding: 0;"] search.icq.com##.res_sp techrepublic.com##.resource-centre intelius.com##.resourceBox cio.com,informationweek.com##.resources website-unavailable.com##.response macmillandictionary.com##.responsive_cell_whole simplefilesearch.com##.result-f wrongdiagnosis.com##.result_adv yellowpages.bw,yellowpages.co.ls,yellowpages.co.zm##.result_item_gold yellowpages.bw,yellowpages.co.ls,yellowpages.co.zm##.result_item_silver torrents.de,torrentz.ch,torrentz.com,torrentz.eu,torrentz.in,torrentz.li,torrentz.me,torrentz.ph##.results > h3 > div[style="text-align:center"] hotbot.com##.results-top yellowbook.com##.resultsBanner nickjr.com##.resultsSponsoredBy cardomain.com##.resultsTableCol movies.yahoo.com##.results[bgcolor="#ECF5FA"] vmn.net##.results_sponsor queentorrent.com##.results_table > tbody > :nth-child(-n+4) yauba.com##.resultscontent:first-child classifiedads.com##.resultspon bitcandy.com##.rev_cont_below crooksandliars.com##.revblock hindustantimes.com##.rft_logos alltheragefaces.com##.rg popeater.com##.rgtPane mail.google.com##.rh > #ra pv-magazine.com##.ric_rot_banner siteslike.com##.rif marieclaire.co.uk,search.smartaddressbar.com,usnewsuniversitydirectory.com##.right yourepeat.com##.right > .bigbox:first-child intoday.in##.right-add jrn.com##.right-banner linuxinsider.com,macnewsworld.com##.right-bb greenbiz.com,greenerdesign.com##.right-boom-small scoop.co.nz##.right-box ticotimes.net##.right-carrousel mediabistro.com##.right-column-boxes-content-partners kovideo.net##.right-def-160 movies.yahoo.com##.right-module bloomberg.com##.right-rail-bkg hiphopearly.com##.right-side republicbroadcasting.org##.right-sidebar-padder > #text-7 realclearworld.com##.right-wide-skyscraper 10minutemail.net##.rightBig timeout.com##.rightCol ghanaweb.com##.rightSkyscraper prevention.com##.rightSubBoxArea themoscowtimes.com##.right_banner screenindia.com##.right_blank2 livescience.com##.right_content > .side_row cybergamer.com##.right_dvrtsmnt electronista.com,ipodnn.com,macnn.com##.right_footer softicons.com##.right_ga legalbusinessonline.com##.right_job_bg01 mosnews.com##.right_pop huffingtonpost.ca##.right_rail_edit_promo veryfunnyads.com##.right_sponsor gumtree.co.za,virtualmedicalcentre.com##.rightbanner tuvaro.com##.rightbar-inside blekko.com##.rightbar-inside > div + div + .note blekko.com##.rightbar-inside > div + div + .note + ul[id] findlaw.com##.rightcol_300x250 findlaw.com##.rightcol_sponsored coolest-gadgets.com##.rightcolbox[style="height: 250px;"] computerworld.co.nz##.rightcontent khmertimeskh.com##.rightheader bikesportnews.com##.rightmpu press-citizen.com##.rightrail-promo theteachercorner.net##.rightside gametrailers.com##.rightthin_content lyricsfreak.com##.ringtone audiko.net##.ringtone-banner-top songlyrics.com##.ringtone-matcher lyricsfreak.com##.ringtone_b dilandau.eu##.ringtone_button lyricsty.com##.ringtone_s clip.dj##.ringtonemakerblock idolator.com##.river-interstitial ratemyprofessors.com##.rmp_leaderboard techpowerup.com##.rnav_d techpowerup.com##.rnav_e theyeshivaworld.com##.rndm theyeshivaworld.com##.rndm10 theyeshivaworld.com##.rndm2 theyeshivaworld.com##.rndm6 theyeshivaworld.com##.rndm7 theyeshivaworld.com##.rndm9 ballinaadvocate.com.au,bigrigs.com.au,byronnews.com.au,caboolturenews.com.au,centraltelegraph.com.au,coffscoastadvocate.com.au,coolum-news.com.au,cqnews.com.au,dailyexaminer.com.au,dailymercury.com.au,echonews.com.au,frasercoastchronicle.com.au,gattonstar.com.au,gladstoneobserver.com.au,gympietimes.com.au,ipswichadvertiser.com.au,news-mail.com.au,noosanews.com.au,northernstar.com.au,qt.com.au,rangenews.com.au,ruralweekly.com.au,southburnetttimes.com.au,stanthorpeborderpost.com.au,sunshinecoastdaily.com.au,suratbasin.com.au,thechronicle.com.au,themorningbulletin.com.au,thereporter.com.au,thesatellite.com.au,tweeddailynews.com.au,warwickdailynews.com.au,whitsundaytimes.com.au##.rnn_ri_container_compare-and-container-containere craveonline.com,momtastic.com,realitytea.com,superherohype.com##.roadblock surinenglish.com##.robapaginas roblox.com##.roblox-skyscraper euronews.com##.rolexLogo cbslocal.com##.rotatable theatlantic.com##.rotating-article-promo impactwrestling.com,newswireless.net##.rotator leadership.ng##.rotor leadership.ng##.rotor-items[style="width: 300px; height: 260px; visibility: visible;"] toolslib.net##.row > .col-md-5 > .rotate-90 lonelyplanet.com##.row--leaderboard bikechatforums.com##.row1[style="padding: 5px;"] bikechatforums.com##.row2[style="padding: 5px;"] istockanalyst.com##.rr aol.com##.rrpromo freewebarcade.com##.rsads techmeme.com##.rsp herold.at##.rssBox newstrackindia.com##.rt-add336x280 rockthebells.net##.rtb-bot-banner-row computerweekly.com##.rtx news24.com,sport24.co.za,women24.com##.rubyContainer 6scoops.com,9gag.com##.s-300 listverse.com##.s-a virginmedia.com##.s-links surfthechannel.com,watchseries.ag,watchseries.lt,watchseries.vc,watchseriesuk.ag,watchseriesuk.lt,watchtvseries.se,watchtvseries.vc##.s-mpu-list business-standard.com##.s-s wwtdd.com##.s728x90 igossip.com##.s9 farmtrader.co.nz,motorcycletrader.co.nz,tradeaboat.co.nz##.sBanner search.charter.net,search.frontier.com##.sBrSpns dnsrsearch.com,dnssearch.rr.com,search.charter.net,search.frontier.com##.sRsltHld pipl.com##.s_links pipl.com##.s_tips asiator.net##.sa legacy.com##.sa_Table mouseprice.com##.salerent_advt pinoyexchange.com##.sampleAmazon pinoyexchange.com##.sampleLayout[style="height:110px;"] globalpost.com##.sap-permalink localjewishnews.com##.sayfalist1 > .widgets:first-child + .widgets + .widgets + .widgets:last-child scienceblogs.com##.sb-sponsor usmagazine.com##.sb_logo thedirty.com##.sbanner 4kidstv.com##.sbbox1 skybreezegames.com##.sbg-160 skybreezegames.com##.sbg-728 mobilebloom.com##.sbpricing bitcoinblogger.com##.sc_ads_within_one scmp.com##.scmp_advert-tile skysports.com##.score-bet slack-time.com##.scraper drizzydrake.org##.scrbl farmanddairy.com##.screen-4 phonedog.com##.scribol stardoll.com##.sdadinfo stardoll.com##.sdadinfoTrans ebay.co.uk##.sdcBox itproportal.com##.se_left itproportal.com##.se_right blogger-index.com,sedoparking.com##.search lavasoft.com##.search > .spdiv:first-child lavasoft.com##.search > .spdiv:last-child kovideo.net##.search-728 search.freefind.com##.search-headline-table start.mysearchdial.com##.search-list + .mts + .search-list torrents.net##.search-results howstuffworks.com##.search-span yellowise.com##.search-title[style="color: #666;padding:0;margin:0;"] muzu.tv##.searchMPUSlot startpins.com##.searchResultsBottom somoto.com##.searchResultsRight startpins.com##.searchResultsTop bhg.com##.searchSponsors youtube.com##.searchView.list-view kibagames.com##.search_adv_container linxdown.me##.search_link_box brothersoft.com##.search_sponor linxdown.com##.searchblock torrenthound.com##.searchtable:first-child gaystarnews.com##.sechead3-right vogue.co.uk##.secondary-content-banner-box vogue.co.uk##.secondary-content-mpu-box citysearch.com##.secondaryText xml.com##.secondary[width="153"] pornhub.com##.section-hqrelateds slidetoplay.com##.section-sponsor free-codecs.com##.sectionBanners thevarguy.com##.sectionbreak2 babylon.com,search.chatzum.com##.sectionheadertopltr ask.reference.com##.sectiontitle fredericknewspost.com##.select[width="148"] codeinspot.com##.sen1 sheryna.com.my##.sense2 sheryna.com.my##.sense_h0 sheryna.com.my##.sensel1 time.com##.sep twikle.com##.separ_box_small + .small activistpost.com##.separator[style="clear: both; text-align: center;"] pixabay.com##.separator_box[style="min-width: 960px;"] filesocean.net,linexdown.net,rapidfiledownload.com##.serchblock rapidfiledownload.com##.serchblockrfd filesocean.net,linexdown.net,rapidfiledownload.com##.serchbox rapidfiledownload.com##.serchboxrfd espncricinfo.com##.seriesSpncr charter.net,verizon.com##.serp21_sponsored sfgate.com##.sfg_ysm001 zeetv.com##.sh_banner1 04stream.com##.shade foxstart.com##.shadow arto.com##.shadowBoxBody good.is##.shadow[style="padding:10px;"] good.is##.shadow[style="padding:10px;width:728px;"] forbes.com##.shareMagazine zdnet.com##.shared-resource-center newgrounds.com##.shareicons 4shared.com##.sharemore laughingsquid.com##.sharethrough-placement yahoo.com##.sharing-toolbar shopping.yahoo.com##.shmod-ysm coderanch.com##.shngl bhg.com##.shopNation dailylife.com.au##.shopStyle-widget cnet.com##.shopperSpecials tomshardware.com##.shopping caranddriver.com,roadandtrack.com##.shopping-tools nzherald.co.nz##.shoppingContainer deccanherald.com##.shoppingContent musicradar.com##.shopping_partners yumsugar.com##.shopstyle-sidebar-content ocworkbench.com##.shopwidget1 funnyordie.com##.short-mrec skins.be##.shortBioShadowB spike.com##.show_branding_holder autos.msn.com##.showcase zillow.com##.showcase-outline crunchyroll.com##.showmedia-tired-of-ads complex.com##.side-300x600 makeuseof.com,viva.co.nz##.side-banner apptism.com##.side-banner-holder metrolyrics.com##.side-box.clearfix desktopreview.com##.side-resouresc sankakucomplex.com##.side120c sankakucomplex.com##.side120xmlc bvblackspin.com,bvonmoney.com,bvonmovies.com##.sideBanner tomsguide.com,tomshardware.com##.sideOffers weatherology.com##.side_165x100 telecompaper.com##.side_banner wow-europe.com##.side_banner_305x133 panarmenian.net##.side_panner businessnewsdaily.com##.side_row[style="text-align:center;"] newburytoday.co.uk##.side_takeover_inner electricpig.co.uk##.side_wide_banner blackpenguin.net,newburytoday.co.uk##.sidebar weknowmemes.com##.sidebar > .widgetcontainer linksfu.com##.sidebar > ul > .sidebox thejointblog.com##.sidebar img[width="235"][height="150"] reelseo.com##.sidebar-125-box reelseo.com##.sidebar-125-events makeuseof.com##.sidebar-banner infdaily.com##.sidebar-box2 infdaily.com##.sidebar-box4 ditii.com##.sidebar-left rte.ie##.sidebar-mpu blogtechnical.com##.sidebar-outline techti.me##.sidebar-promotion g4chan.com##.sidebar-rectangle techi.com##.sidebar-rectangle-banner timesofisrael.com##.sidebar-spotlight techi.com##.sidebar-square-banner davidwalsh.name##.sidebar-treehouse indianapublicmedia.org##.sidebar-upper-underwritings thebadandugly.com##.sidebar30 comicsalliance.com,lemondrop.com,popeater.com,urlesque.com##.sidebarBanner urgames.com##.sidebarBar urgames.com##.sidebarScrapper cghub.com##.sidebar_banner instantshift.com##.sidebar_banners_bottom instantshift.com##.sidebar_banners_top instantshift.com##.sidebar_bsa_mid01 instantshift.com##.sidebar_bsa_top02 gpforums.co.nz##.sidebar_mm_block domainnamewire.com##.sidebar_promotions_small mediacomcable.com##.sidebar_sponsored geektyrant.com##.sidebar_support instantshift.com##.sidebar_vps_banner bridgemi.com##.sidebarboxinvest thenokiablog.com##.sidebardirect smashingmagazine.com##.sidebared sankakucomplex.com##.sidebartopb sankakucomplex.com##.sidebartopc scotusblog.com##.sidebarwidgeted > .text-21 freedla.com##.sidebox tothepc.com##.sidebsa ohinternet.com##.sider yttalk.com##.sidevert yttalk.com##.sidevert2 nabble.com##.signature zerohedge.com##.similar-box greatis.com##.sing cryptothrift.com##.single-auction-ad infosecurity-magazine.com##.site-leaderboard fxstreet.com,macstories.net##.site-sponsor faithtalk1500.com,kfax.com,wmca.com##.siteWrapLink itproportal.com##.site_header cracked.com##.site_sliver crackdb.cd##.sitename:first-child + br + h1:last-child inthesetimes.com##.sites-of-interest 9gag.tv##.size-728x90 kwgn.com##.size_230_90 indeed.co.uk,indeed.com##.sjas2 indeed.co.uk,indeed.com##.sjl indeed.com##.sjl0 indeed.co.uk,indeed.com##.sjl1t bit.com.au##.skin-btn autocarindia.com##.skin-link tennisworldusa.org##.skin1 videogamer.com,zdnet.com##.skinClick entrepreneur.com,newstatesman.com##.sky miniclip.com##.sky-wrapper skysports.com##.skyBetLinkBox petoskeynews.com##.skyScraper football365.com##.skybet aol.co.uk##.skybet-art skysports.com##.skybet-odds-link football365.com##.skybet-space planet-rugby.co.za,planetf1.com,planetrugby.com##.skybetbar eweek.com##.skylabel games2c.com,knowyourmobile.com,mymovies.net##.skyright bigtennetwork.com,californiareport.org,columbiatribune.com,comicbookresources.com,computerweekly.com,crackberry.com,datpiff.com,emedtv.com,engadget.com,etonline.com,evilmilk.com,gd.tuwien.ac.at,guanabee.com,gumtree.co.za,infosecurity-magazine.com,iwatchstuff.com,keyetv.com,kqed.org,l4dmaps.com,ludobox.com,moneyweek.com,pastemagazine.com,pcworld.com,planetrock.com,pulse.co.uk,scienceblogs.com,sciencedaily.com,sportsvibe.co.uk,topgear.com,weartv.com,webshots.com,wrc.com##.skyscraper infosecurity-magazine.com##.skyscraper-button democraticunderground.com,sciencedaily.com##.skyscraper-container democraticunderground.com##.skyscraper-placeholder gmx.com##.skyscraperClass lookbook.nu,tucsoncitizen.com##.skyscraper_container telegram.com##.skyscraper_in_narrow_column freshbusinessthinking.com##.skyscraper_lft freshbusinessthinking.com##.skyscraper_rgt_btm freshbusinessthinking.com##.skyscraper_rgt_top dosgamesarchive.com##.skyscraper_small fog24.com,futbol24.com##.skyscrapper search.ch##.sl_banner slacker.com##.slacker-sidebar-ad slant.investorplace.com##.slant-sidebar-ad-tag cnet.com.au##.slb manchesterconfidential.co.uk##.sldr drugs.com##.slider-title bikeradar.com##.slider-vert thebeachchannel.tv##.slideshow kcra.com,ketv.com,kmbc.com,wcvb.com,wpbf.com,wtae.com##.slideshowCover bonappetit.com##.slideshow_sidebar_divider thephuketnews.com##.slidesjs-container burbankleader.com,citypaper.com,dailypilot.com,glendalenewspress.com,hbindependent.com,lacanadaonline.com,vacationstarter.com,vagazette.com##.slidingbillboard foodfacts.com##.slimBanner ecommercetimes.com##.slink-text ecommercetimes.com##.slink-title inbox.com##.slinks theguardian.com##.slot__container mail.ru##.slot_left ap.org,euractiv.com,mnn.com,newsweek.com,slashdot.org##.slug mirror.co.uk##.sm-promo-list pixelatedgeek.com##.small-leaderboard ten.com.au##.small-listing.small-listing4.google farmanddairy.com##.small-quad-banner dealsonwheels.com##.small-text hitsquad.com##.small-title tbs.com##.smallBanners pdnonline.com##.smallGrayType rottentomatoes.com##.small[style="margin-top:10px;"] monhyip.net##.small_banner empireonline.com##.smallgrey[height="250"] dressupone.com##.smallpreviewpubgoogle duluthnewstribune.com##.smalltxt gamefreaks.co.nz##.smltxt musicmaza.com##.smtxt computerworlduk.com##.socialMediaBoxout dawn.com##.soft-half--top.soft-half--sides fanhow.com##.softhalf softpile.com##.softitem afreecodec.com##.softshot elyrics.net##.songring greatandhra.com##.sortable-item_top_add crawler.com,phonebook.com.pk##.sp watch-series.ag,watch-tv-series.to,watchseries.ag,watchseries.lt,watchseries.ph,watchseries.vc,watchseriesuk.ag,watchseriesuk.lt,watchtvseries.se,watchtvseries.vc##.sp-leader watch-series.ag,watch-tv-series.to,watchseries.ag,watchseries.lt,watchseries.p,watchseries.vc,watchseriesuk.ag,watchseriesuk.lt,watchtvseries.se,watchtvseries.vc##.sp-leader-bottom pcmag.com##.sp-links filestube.to##.spF filestube.to##.spL mywebsearch.com##.spLinkCon rapid-search-engine.com##.sp_header money.msn.com##.spadr channelchooser.com##.span-12.prepend-top.last foodingredientsfirst.com##.span-24.last[style="z-index: 1; height: 90px;"] nutritionhorizon.com##.span-24[style="z-index: 1; height: 90px;"] nationmultimedia.com##.span-7-1[style="height:250px; overflow:hidden;"] kcsoftwares.com##.span2.well picosearch.com##.spblock askmen.com##.special newsweek.com##.special-insight fashionmagazine.com##.special-messages pcmag.com##.special-offers euronews.com##.specialCoveragePub nzherald.co.nz##.specialOffers msn.co.nz##.special_features livescience.com##.special_link weddingchannel.com##.specialoffers macobserver.com##.specials thenextweb.com##.speeb_widget reference.com##.spl_adblk ask.com##.spl_shd_plus ask.com,reference.com,search-results.com,thesaurus.com##.spl_unshd reference.com##.spl_unshd_NC giveawayoftheday.com##.splinks listverse.com##.split yahoo.com##.spns informer.com##.spnsrd smashingmagazine.com##.spnsrlistwrapper everyclick.com,info.co.uk,info.com,travel.yahoo.com##.spon worldtimezone.com##.spon-menu yahoo.com##.spon.clearfix aol.com##.spon_by autos.aol.com##.spon_link_new quakelive.com##.spon_media msn.com##.sponby technologyreview.com##.sponcont radiozindagi.com##.sponeser mediagazer.com##.sponrn pho.to,smartwebby.com,workhound.co.uk,yahoo.com##.spons blekko.com##.spons-res njuice.com,wwitv.com##.sponsb 1310news.com,2oceansvibe.com,964eagle.co.uk,abc22now.com,airliners.net,animepaper.net,app.com,ar15.com,austinist.com,b100quadcities.com,bexhillobserver.net,blackpoolfc.co.uk,blackpoolgazette.co.uk,bloomberg.com,bognor.co.uk,bostonstandard.co.uk,brisbanetimes.com.au,brothersoft.com,businessinsider.com,canberratimes.com.au,cbslocal.com,cd1025.com,chicagoist.com,chichester.co.uk,concordmonitor.com,dcist.com,domainincite.com,eastbourneherald.co.uk,electricenergyonline.com,europages.co.uk,gamingcloud.com,gothamist.com,halifaxcourier.co.uk,hastingsobserver.co.uk,hellomagazine.com,homelife.com.au,informationweek.com,isearch.igive.com,khak.com,kkyr.com,kosy790am.com,kpbs.org,ktla.com,kygl.com,laist.com,lcfc.com,lep.co.uk,limerickleader.ie,lmgtfy.com,mg.co.za,mix933fm.com,networkworld.com,newrepublic.com,news1130.com,newsweek.com,nocamels.com,nouse.co.uk,pastie.org,pogo.com,portsmouth.co.uk,power959.com,prestontoday.net,proactiveinvestors.com,proactiveinvestors.com.au,publicradio.org,rock1049.com,rte.ie,scotsman.com,sfist.com,shieldsgazette.com,skysports.com,smh.com.au,spaldingtoday.co.uk,star935fm.com,sunderlandecho.com,techonomy.com,theage.com.au,thescarboroughnews.co.uk,thestar.co.uk,theworld.org,userscripts.org,variety.com,verizon.net,videolan.org,washingtonpost.com,watoday.com.au,wayfm.com,wfnt.com,wigantoday.net,wklh.com,wscountytimes.co.uk,wsj.com,yorkshireeveningpost.co.uk,yorkshirepost.co.uk,zdnet.co.uk,zuula.com##.sponsor search.comcast.net##.sponsor-6 kiswrockgirls.com##.sponsor-banner bbc.com##.sponsor-container search.yahoo.com##.sponsor-dd pcmag.com##.sponsor-head theweek.co.uk##.sponsor-image diynetwork.com##.sponsor-lead houserepairtalk.com,soapmakingforum.com##.sponsor-list broncos.com.au,cfo.com,cowboys.com.au,dragons.com.au,newcastleknights.com.au,parraeels.com.au,penrithpanthers.com.au,rabbitohs.com.au,raiders.com.au,roosters.com.au,seaeagles.com.au,sharks.com.au,titans.com.au,warriors.co.nz,weei.com,weststigers.com.au##.sponsor-logo tricycle.com##.sponsor-logo-image oilprice.com##.sponsor-slider theroot.com##.sponsor-slot-hp mnn.com##.sponsor-title-image theweek.co.uk##.sponsor-top linux-mag.com##.sponsor-widget tumblr.com##.sponsor-wrap clgaming.net##.sponsor-wrapper 411.com,whitepages.com,wprugby.com##.sponsor1 msn.com,wprugby.com##.sponsor2 msn.com,wprugby.com##.sponsor3 dptv.org##.sponsor300 arizonasports.com,ktar.com##.sponsorBy wsj.com##.sponsorContainer investors.com##.sponsorFt forbes.com,nzherald.co.nz##.sponsorLogo dlife.com##.sponsorSpecials blbclassic.org##.sponsorZone channel5.com##.sponsor_container bolandrugby.com##.sponsor_holder videolan.org##.sponsor_img go963mn.com##.sponsor_strip sat-television.com,satfriends.com,satsupreme.com##.sponsor_wrapper freeyourandroid.com##.sponsorarea vancouversun.com##.sponsorcontent buump.me##.sponsord monsterindia.com##.sponsoreRes monsterindia.com##.sponsoreRes_rp 24hrs.ca,92q.com,abovethelaw.com,app.com,argusleader.com,asktofriends.com,azdailysun.com,battlecreekenquirer.com,baxterbulletin.com,break.com,bucyrustelegraphforum.com,burlingtonfreepress.com,centralohio.com,chillicothegazette.com,chronicle.co.zw,cincinnati.com,cio.com,citizen-times.com,clarionledger.com,cnbc.com,cnet.com,coloradoan.com,computerworld.com,coshoctontribune.com,courier-journal.com,courierpostonline.com,dailyrecord.com,dailyworld.com,defensenews.com,delawareonline.com,delmarvanow.com,desmoinesregister.com,divamag.co.uk,dnj.com,examiner.co.uk,express.co.uk,fdlreporter.com,federaltimes.com,findbestvideo.com,floridatoday.com,freep.com,funnyordie.com,geektime.com,govtech.com,greatfallstribune.com,greenbaypressgazette.com,greenvilleonline.com,guampdn.com,hattiesburgamerican.com,hellobeautiful.com,herald.co.zw,hometownlife.com,hotklix.com,htrnews.com,imgur.com,indystar.com,infoworld.com,isohunt.to,ithacajournal.com,ixquick.com,jacksonsun.com,javaworld.com,jconline.com,knoworthy.com,lansingstatejournal.com,lfpress.com,livingstondaily.com,lohud.com,lycos.com,mansfieldnewsjournal.com,marionstar.com,marketingland.com,marshfieldnewsherald.com,montgomeryadvertiser.com,mycentraljersey.com,mydesert.com,mywot.com,networkworld.com,newarkadvocate.com,news-leader.com,news-press.com,newsleader.com,newsone.com,niagarafallsreview.ca,noscript.net,nugget.ca,pal-item.com,pcworld.com,phoenixnewtimes.com,pnj.com,portclintonnewsherald.com,postcrescent.com,poughkeepsiejournal.com,press-citizen.com,pressconnects.com,racinguk.com,rapidlibrary.com,rgj.com,salon.com,scottishdailyexpress.co.uk,sctimes.com,searchengineland.com,seroundtable.com,sheboyganpress.com,shreveporttimes.com,slate.com,stargazette.com,startpage.com,statesmanjournal.com,stevenspointjournal.com,tallahassee.com,tennessean.com,theadvertiser.com,theatlantic.com,thebarrieexaminer.com,thecalifornian.com,thedailyjournal.com,thedailyobserver.ca,theguardian.com,theleafchronicle.com,thenews-messenger.com,thenewsstar.com,thenorthwestern.com,theobserver.ca,thepeterboroughexaminer.com,thespectrum.com,thestarpress.com,thetimesherald.com,thetowntalk.com,torrentz.in,torrentz.me,trovit.co.uk,visaliatimesdelta.com,washingtonpost.com,wausaudailyherald.com,wheels.ca,wisconsinrapidstribune.com,yippy.com,zanesvilletimesrecorder.com##.sponsored gardensillustrated.com##.sponsored-articles citizen.co.za,policeone.com##.sponsored-block general-files.com##.sponsored-btn advisorone.com,cutimes.com,futuresmag.com##.sponsored-by geektime.com##.sponsored-channel chron.com,slate.com##.sponsored-content itproportal.com##.sponsored-hub fbdownloader.com##.sponsored-info techtipsgeek.com##.sponsored-level usnews.com##.sponsored-listing thestar.com##.sponsored-listings arstechnica.com##.sponsored-rec dailystar.co.uk,standardmedia.co.ke##.sponsored-section computerandvideogames.com##.sponsored-slideshow futuresmag.com##.sponsored-tops politico.com##.sponsored-wrapper windowsitpro.com,winsupersite.com##.sponsoredAnnouncementWrap citywire.co.uk,fool.com,offshore-mag.com##.sponsoredBy downloadcrew.com##.sponsoredDownloads gamesforthebrain.com##.sponsoredGames investing.businessweek.com##.sponsoredHeader eluta.ca##.sponsoredJobsTable iol.co.za##.sponsoredLinksList technologyreview.com##.sponsored_bar generalfiles.me##.sponsored_download news24.com##.sponsored_item jobs.aol.com##.sponsored_listings tumblr.com##.sponsored_post funnyordie.com##.sponsored_videos 1337x.org##.sponsoredname news-medical.net##.sponsorer-note classifiedads.com##.sponsorhitext dailyglow.com##.sponsorlogo premierleague.com##.sponsorlogos affiliatesrating.com,allkpop.com,androidfilehost.com,arsenal.com,audiforums.com,blueletterbible.org,canaries.co.uk,capitalfm.co.ke,dolliecrave.com,eaglewavesradio.com.au,foodhub.co.nz,freshwap.me,geckoforums.net,health24.com,herold.at,keepvid.com,lake-link.com,meanjin.com.au,morokaswallows.co.za,nesn.com,quotes.net,thebulls.co.za,thedailywtf.com,thinksteroids.com,wbal.com,yellowpageskenya.com##.sponsors herold.at##.sponsors + .hdgTeaser herold.at##.sponsors + .hdgTeaser + #karriere pri.org##.sponsors-logo-group keepvid.com##.sponsors-s appadvice.com##.sponsorsAside pwnage.tv##.sponsors_bar edie.net##.sponsors_bottom pdfzone.com##.sponsors_container livemint.com##.sponsors_logo_newspon driverdb.com##.sponsors_table edie.net##.sponsors_top newsweek.com,speroforum.com,theolympian.com,theonion.com##.sponsorship news1130.com,news919.com,news957.com,sonicnation.ca##.sponsorship-block seahawks.com##.sponsorship-bottom createjs.com##.sponsorship-menu accesshollywood.com##.sponsorships law.com##.sponsorspot yellowpageskenya.com##.sponsorsz nu2.nu##.sponsortable newswiretoday.com,przoom.com##.sponsortd nydailynews.com##.sponspored blekko.com##.sponsres superpages.com##.sponsreulst tuvaro.com##.sponsrez wwitv.com##.sponstv dailymail.co.uk,mailonsunday.co.uk##.sport.item > .cmicons.cleared.bogr3.link-box.linkro-darkred.cnr5 alexandriagazette.com,arlingtonconnection.com,burkeconnection.com,centre-view.com,connection-sports.com,emporis.com,fairfaxconnection.com,fairfaxstationconnection.com,garfield.com,greatfallsconnection.com,herndonconnection.com,kusports.com,mcleanconnection.com,mountvernongazette.com,potomacalmanac.com,reston-connection.com,springfieldconnection.com,union-bulletin.com,viennaconnection.com##.spot thewhir.com##.spot-125x125 thewhir.com##.spot-234x30 thewhir.com##.spot-728x90 steamboattoday.com##.spot500 wunderground.com##.spotBox pcmag.com##.spotlight jpost.com##.spotlight-long edmunds.com##.spotlight-set jpost.com##.spotlight-single u-file.net##.spottt_tb drum.co.za,thejuice.co.za##.spreetv--container digitalmemo.net##.spresults walmart.com##.sprite-26_IMG_ADVERTISEMENT_94x7 picosearch.com##.sptitle limelinx.com##.sqBanner bayt.com,booyapictures.com,industryweek.com,milesplit.com##.square biography.com##.square-advertisment-module-second-column mixcloud.com##.square-bottom port2port.com##.squareBanner vibevixen.com##.square_300 thevarguy.com##.squarebanner160x160 baseball-reference.com##.sr_draftstreet downbyte.net,linxdown.com,redown.se##.srchbox redown.se##.srchtitle realliving.com.ph##.srec buenosearch.com,delta-search.com,holasearch.com##.srmadb buenosearch.com##.srmads delta-search.com##.srmah starsports.com##.ss-mrec-align skysports.com##.ss-sponsor law.com##.ssp_outer coolspotters.com##.stack forumpromotion.net##.staff-affiliates nst.com.my##.standard thesportreview.com##.standard-MPU citytalk.fm##.standard-mpu-widget citytalk.fm##.standard-skyscraper-widget leo.org##.standard_banner stardoll.com##.stardollads simplyassist.co.uk##.std_BottomLine pcauthority.com.au##.storeWidget pcauthority.com.au##.storeWidgetBottom punchng.com##.story-bottom abcnews.go.com##.story-embed-left.box m.facebook.com,touch.facebook.com##.storyStream > ._6t2[data-sigil="marea"] m.facebook.com,touch.facebook.com##.storyStream > .fullwidth._539p m.facebook.com,touch.facebook.com##.storyStream > article[id^="u_"]._676 m.facebook.com,touch.facebook.com##.storyStream > article[id^="u_"].storyAggregation straitstimes.com##.story_imu hindustantimes.com##.story_lft_wid swns.com##.story_mpu pdfzone.com##.storybox brisbanetimes.com.au,theage.com.au,watoday.com.au##.strapHeadingDealPartner twitter.com##.stream-item[data-item-type="tweet"][data-item-id*=":"] bitshare.com##.stream_flash_overlay bangkok.com##.strip-banner-top people.com,peoplepets.com##.stylefind people.com##.stylefindtout videohelp.com##.stylenormal[width="24%"][valign="top"][align="left"] complex.com##.sub-div lolhome.com##.subPicBanner ratemyteachers.com##.sub_banner_728 deviantart.com,sta.sh##.subbyCloseX ycuniverse.com##.subheader_container businessinsider.com##.subnav-container viralviralvideos.com##.suf-horizontal-widget interaksyon.com##.super-leader-board t3.com##.superSky djtunes.com##.superskybanner wamu.org##.supportbanner listio.com##.supporter spyka.net##.swg-spykanet-adlocation-250 eweek.com##.sxs-mod-in eweek.com##.sxs-spon tourofbritain.co.uk##.sys_googledfp sedoparking.com##.system.links emoneyspace.com##.t_a_c movreel.com##.t_download torrentbit.net##.t_splist dealsofamerica.com##.tab_ext whatsthescore.com##.table-odds newsbtc.com##.table-responsive thescore.com##.tablet-big-box thescore.com##.tablet-leaderboard relevantradio.com##.tabs torrents.to##.tad suvudu.com##.tad-block-outer coldwellbanker.com##.tag247-728x90Wrapper jetsetta.com##.tags_2 fhm.com##.takeOverContainer bigjohnandamy.com,bmwblog.com,brobible.com,miniclip.com##.takeover recombu.com##.takeover-left flicks.co.nz##.takeover-link recombu.com##.takeover-right speedtv.com##.takeover_link tamilyogi.tv##.tamilyogi taste.com.au##.taste-leaderboard-ad fulldls.com##.tb_ind koreaherald.com##.tbanner lordtorrent3.ru##.tbl-striped anoox.com##.tbl_border[bgcolor="#fff9dd"] csschat.com##.tborder[width="100%"] + center websleuths.com##.tborder[width="140"] ironmagazineforums.com##.tborder[width="150"] genesisowners.com##.tborder[width="160"] hgtv.com##.tcap hiphopearly.com##.td-468 thespec.com##.td-Home_Sponsor mobiletor.com##.td-footer-wrap gixen.com##.td_bck3 toronto.com##.td_featured soccerway.com##.team-widget-wrapper-content-placement 4shared.com,itproportal.com##.teaser mmegi.bw##.template_leaderboard_space dirpy.com##.text-center[style="margin-top: 20px"] dirpy.com##.text-center[style="margin-top: 20px;display: block;"] adelaidenow.com.au##.text-g-an-web-group-news-affiliate couriermail.com.au##.text-g-cm-web-group-news-affiliate perthnow.com.au##.text-g-pn-web-group-news-affiliate news.com.au##.text-g-tech-rh-panel-compareprices najoomi.com##.text-left > .span11 news.com.au##.text-m-news-tech-iframe-getprice-widget-rhc jekoo.com##.textCollSpons sportschatplace.com##.textLink msnbc.msn.com,nbcnews.com##.textSmallGrey linksave.in##.text[align="center"] > table[width="513"][cellspacing="0"][cellpadding="0"][border="0"]:last-child gamechix.com##.text[style="margin:28px 0 0 0;width:95%;text-align:center;"] macsurfer.com##.text_top_box kqed.org##.textsponsor evilbeetgossip.com,knowelty.com##.textwidget travel.yahoo.com##.tgl-block wdet.org##.thanks pushsquare.com##.the-right nintendolife.com##.the300x250 vaughnlive.tv##.theAboutWrap seedmagazine.com##.theAd burntorangereport.com##.theFlip thonline.com##.thheaderweathersponsor vogue.com##.thin_banner hqq.tv##.this_pays thesaturdaypaper.com.au##.thp-wrapper y100.com##.threecolumn_rightcolumn affiliates4u.com##.threehundred supercompressor.com##.thrillist-ad time4tv.com##.thumbimg thinkdigit.com##.thumbnails dt-updates.com##.thx > .bottomBorderDotted + .block[style]:last-child razorianfly.com##.ticker nytimes.com##.ticketNetworkModule nbcsports.msnbc.com##.ticketsnow-widget cointelegraph.com##.timeline-promo newsfactor.com##.tinText pichunter.com##.tiny cincinnati.com##.tinyclasslink aardvark.co.nz##.tinyprint softwaredownloads.org##.title2 sumotorrent.sx##.title_green[align="left"][style="margin-top:18px;"] + table[cellspacing="0"][cellpadding="0"][border="0"] domains.googlesyndication.com##.title_txt02 wambie.com##.titulo_juego1_ad_200x200 myspace.com##.tkn_medrec centredaily.com##.tla tldrlegal.com##.tldrlegal-ad-space independent.co.uk##.tm_140_container independent.co.uk##.tm_300_container timeout.com##.to-offers ghanaweb.com##.tonaton-ads mp3lyrics.org##.tonefuse_link newsok.com##.toolbar_sponsor investopedia.com,runescape.com,thehill.com##.top warezchick.com##.top > p:last-child searchza.com,webpronews.com##.top-750 9to5google.com,animetake.com,arabianbusiness.com,brainz.org,dailynews.gov.bw,ebony.com,extremesportman.com,firsttoknow.com,leadership.ng,leedsunited.com,letstalkbitcoin.com,reverso.net,rockthebells.net,spanishdict.com,torrentreactor.com,torrentreactor.net,weeklyworldnews.com##.top-banner manicapost.com##.top-banner-block rumorfix.com##.top-banner-container citymetric.com##.top-banners thekit.ca##.top-block golf365.com##.top-con azdailysun.com,billingsgazette.com,bismarcktribune.com,hanfordsentinel.com,journalstar.com,lompocrecord.com,magicvalley.com,missoulian.com,mtstandard.com,napavalleyregister.com,nctimes.com,santamariatimes.com,stltoday.com##.top-leader-wrapper 931dapaina.com,politico.com,sciencedaily.com##.top-leaderboard film.com##.top-leaderboard-container sciencedaily.com##.top-rectangle 1340bigtalker.com##.top-right-banner espnfc.com##.top-row theticketmiami.com##.top-super-leaderboard usniff.com##.top-usniff-torrents livingelectro.com##.top-widget-rect livingelectro.com##.top-widget-rect + .search_bar + .widget-rect + .widget-rect jarkey.net##.top728 aol.ca,aol.com,ap.org,current.com,nerdist.com,reviewgist.com,shelterpop.com,tampabay.com,telegraph.co.uk,wsj.com##.topAd stevedeace.com##.topAddHolder nypress.com##.topAds > div[style="width:1010px;height:100px;\9 overflow: hidden"] celebrity.aol.co.uk,christianpost.com,comicsalliance.com,csnews.com,europeantour.com,gourmetretailer.com,haaretz.com,inrumor.com,jobberman.com,lemondrop.com,pgmeatretailing.com,pricegrabber.com,progressivegrocer.com,singlestoreowner.com,urgames.com,urlesque.com##.topBanner urgames.com##.topBannerBOX onetime.com##.topBannerPlaceholder ebay.co.uk,ebay.com##.topBnrSc techadvisor.co.uk##.topLeader kjonline.com,pressherald.com##.topLeaderboard technomag.co.zw##.topLogoBanner yellowbook.com##.topPlacement search.sweetim.com##.topSubHeadLine2 weatherology.com##.top_660x100 channelstv.com##.top_alert androidcommunity.com,emu-russia.net,freeiconsweb.com,hydrocarbonprocessing.com,kohit.net,novamov.com,praguepost.com,themediaonline.co.za,themoscowtimes.com,voxilla.com,weta.org##.top_banner joebucsfan.com##.top_banner_cont freeridegames.com##.top_banner_container thebatt.com##.top_banner_place sportspagenetwork.com##.top_banner_scoreboard_content gametrailers.com##.top_banner_space itp.net##.top_bit famousbloggers.net##.top_content_banner 977music.com##.top_crv postcourier.com.pg##.top_logo_righ_img wallpapersmania.com##.top_pad_10 babylon.com##.top_right finecooking.com##.top_right_lrec 4chan.org,everydayhealth.com,gamingonlinux.com,goodanime.eu,intothegloss.com,makezine.com,mangashare.com,mirrorcreator.com,rollingout.com,sina.com,thenewstribe.com##.topad filezoo.com,nx8.com,search.b1.org##.topadv gofish.com##.topban1 gofish.com##.topban2 900amwurd.com,bankrate.com,chaptercheats.com,copykat.com,dawn.com,dotmmo.com,downv.com,factmonster.com,harpers.org,mumbaimirror.com,newreviewsite.com,opposingviews.com,softonic.com,thinkdigit.com,weta.org##.topbanner softonic.com##.topbanner_program webstatschecker.com##.topcenterbanner channel103.com,islandfm.com##.topheaderbanner bloggingstocks.com,emedtv.com,gadling.com,minnpost.com##.topleader blackpenguin.net,gamesting.com##.topleaderboard search.ch##.toplinks ndtv.com##.topsponsors_wrap houndmirror.com,torrenthound.com,torrenthoundproxy.com##.topspot yttalk.com##.topv enn.com##.topwrapper kat.ph##.torrentEasyButton bushtorrent.com##.torrent_listing pgatour.com##.tourPlayerFooterAdContainer outdoorchannel.com##.tout_300x250 thecitizen.co.tz##.tower fulldls.com,fulldlsproxy.com,vertor.com##.tp zeenews.com##.tp-add-bg come.in##.tp-banner answers.com##.tp_300x250_3 fulldls.com,torrentzap.com,torrentzapproxy.com,vertor.com##.tp_reccomend_banner emedtv.com##.tpad indiatimes.com##.tpgry pagesinventory.com##.tpromo unlockboot.com##.tr-caption-container trustedreviews.com##.tr-reviews-affiliate 911tabs.com##.tr1 torentilo.com##.trackers + .downloadButton dailymail.co.uk##.travel-booking-links dailymail.co.uk##.travel.item.button_style_module dailymail.co.uk##.travel.item.html_snippet_module nj.com##.travidiatd baltimoresun.com,chicagotribune.com,courant.com,dailypress.com,latimes.com,mcall.com,orlandosentinel.com,redeyechicago.com,sun-sentinel.com##.trb_outfit_sponsorship baltimoresun.com,chicagotribune.com,courant.com,dailypress.com,latimes.com,mcall.com,orlandosentinel.com,redeyechicago.com,sun-sentinel.com##.trb_taboola weather.com##.trc_recs_column + .right-column sitepoint.com##.triggered-cta-box-wrapper-bg thestar.com##.ts-articlesidebar_wrapper google.com,~mail.google.com##.ts[style="margin:0 0 12px;height:92px;width:100%"] techspot.com##.ts_google_ad ask.reference.com##.tsrc_SAS search.vmn.net##.ttl_sponsors infoplease.com##.tutIP-infoarea joebucsfan.com##.tweet_div1 englishrussia.com##.two_leep_box ahk-usa.com,gaccmidwest.org,gaccny.com,gaccsouth.com,gaccwest.com##.tx-bannermanagement-pi1 care2.com##.txt13-vd shaaditimes.com##.txt[style="border: solid 1px #A299A6; background-color: #FDFCFC;"] mail.google.com##.u4 mail.google.com##.u9 villages-news.com##.ubm_premium_banners_rotation villages-news.com##.ubm_premium_rotation_widget blogtv.com##.uc_banner dbforums.com##.ui-widget-overlay[style$="z-index: 1001;"] searchenginewatch.com##.ukn-iab-300x250 searchenginewatch.com##.ukn-u-thanks bitenova.nl,bitenova.org##.un bitenova.nl,bitenova.org##.un_banner wbgo.org##.underwriting sportodin.com,stream4.tv##.unfullscreener afterdawn.com##.uniblue mediaite.com##.unit-wrapper wonderhowto.com##.unverVidAd hottipscentral.com##.unwrapped notebook-driver.com##.updrv siouxcityjournal.com##.upickem-deal-of-the-day memez.com##.upperSideBox uproxx.com##.uproxx_mp_ad christiantoday.com##.usefulLinks downeu.net##.usenet 1337x.org##.usenetDw mnova.eu,monova.org##.usenetd monova.org##.usenextd money-forum.org##.usideblock universetoday.com##.ut_ad_content monova.org##.utext1 monova.org##.uts sportsnet.ca##.v2-3cols-promo sportsnet.ca##.v2-topnav-promo dealsonwheels.co.nz,farmtrader.co.nz,motorcycletrader.co.nz,tradeaboat.co.nz##.vBanner vosizneias.com##.vads lasvegassun.com##.varWrapper indeed.com##.vasu thehill.com##.vbanner thehill.com##.vbanner_center slickdeals.net##.vbmenu_popup + .tborder[align="center"][width="100%"][cellspacing="0"][cellpadding="6"][border="0"] drivearchive.co.uk##.vehicle[style="background-color:#b0c4de"] thelocalweb.net##.verdana9green softpile.com##.versionadv search.yahoo.com##.vert-ad-ttl + * > .eca[target="_blank"][href^="http://r.search.yahoo.com/_ylt="] theverge.com##.vert300 newsnet5.com,wcpo.com,wxyz.com##.vertical-svg ytmnd.com##.vertical_aids praguepost.com##.vertical_banner cnn.com##.vidSponsor thevideo.me##.vid_a8 autoslug.com##.video dailystoke.com,wimp.com##.video-ad drive.com.au##.videoGalLinksSponsored answers.com##.video_1 answers.com##.video_2 thevideo.me##.video_a800 videobam.com##.video_banner fora.tv##.video_plug_space rapidvideo.org##.video_sta timeoutmumbai.net##.videoad2 soccerclips.net##.videoaddright1 straitstimes.com##.view-2014-qoo10-feature euractiv.com##.view-Sponsors moviemet.com##.view-amazon-offers next-gen.biz##.view-featured-job-ad theweek.co.uk##.view-footer themittani.com##.view-game-taxonomy-affiliates healthcastle.com##.view-healthcastle-ads zdnet.com##.view-medusa asiaone.com##.view-qoo10-box talksport.co.uk##.view-ts-sponsor-feature imagebunk.com##.view_banners relink.us##.view_middle_block vidiload.com##.vinfobanner vipleague.co##.vip_006x061 vipleague.co,vipleague.me##.vip_09x827 host1free.com##.virus-information greenoptimistic.com##.visiblebox[style^="position: fixed; z-index: 999999;"] viamichelin.co.uk,viamichelin.com##.vm-pub-home300 n4g.com##.vn-sub searchassist.verizon.com##.vn_searchresults > .vn_results + .vn_rightresults searchassist.verizon.com##.vn_sponsblock sheptonmalletjournal.co.uk##.vouchers centurylink.net##.vp_right vivastreet.co.uk##.vs-summary-300x250 msn.com##.vxp_adContainer dlldll.com##.w0[width="181"] skysports.com##.w10-mpu share-links.biz##.w160.dark.center way2sms.com##.w2mtad msn.com##.w460.clr plumasnews.com##.w49 chinadaily.com.cn##.w980.pt10 ap.org##.wBanner weatherbug.com##.wXcds1 weatherbug.com##.wXcds2 ptf.com,software.informer.com##.w_e xe.com##.wa_leaderboard utrend.tv##.wad sportskrap.com##.wallpaper-link naij.com##.wallpaper__bg naij.com##.wallpaper__top torrentdownloads.net##.warez imdb.com##.watch-bar youtube.com##.watch-extra-info-column youtube.com##.watch-extra-info-right iwannawatch.net##.watch.external channel4.com##.watchLiveOutlinks movie25.cm##.watchnow coolspotters.com##.wau wbal.com##.wbal-banner wincustomize.com##.wc_home_tour_loggedout dir.indiamart.com##.wd1 yahoo.com##.wdpa1 glamourvanity.com##.wdt_gads we7.com##.we7-north timesfreepress.com##.weatherSponsor knowfree.net##.web_link vg.no##.webboard offshore-mag.com##.webcast-promo-box-sponsorname commitstrip.com##.wejusthavetoeat wincustomize.com##.welcome taskcoach.org##.well cosplay.com##.well2[style="padding: 0px; text-align: center; margin-top: 10px"] gearlive.com##.wellvert codinghorror.com##.welovecodinghorror boston.com##.what_is_link soccer365.com##.whiteContentBdr350 techworld.com##.whitePaperContainer hellokids.com##.white_box.r5 torrenthound.com##.whitebg backstage.com##.whitemodbg betanews.com##.whitepapers living.aol.co.uk##.wide.horizontal_promo_HPHT port2port.com##.wideBanner investing.com##.wideBannerBottom footyroom.com##.wideBox inooz.co.uk##.wideContainer netpages.co.za,pch.com,pchgames.com##.wide_banner netpages.co.za##.wide_banner2 newgrounds.com##.wide_storepromo newgrounds.com##.wide_storepromobot roms43.com##.widebanner videogamer.com##.widesky networkworld.com##.wideticker torrentfreak.com##.widg-title soccer24.co.zw##.widget-1 newsbtc.com##.widget-1 > .banner soccer24.co.zw##.widget-2 smartearningsecrets.com##.widget-area hdtvtest.co.uk##.widget-container wikinvest.com##.widget-content-nvadslotcomponent bloombergtvafrica.com,miniclip.com##.widget-mpu thevine.com.au##.widget-shopstyle shanghaiist.com##.widget-skyscraper abovethelaw.com##.widget-sponsor hdtvtest.co.uk##.widget-top dose.ca##.widget_650 fxempire.com##.widget_banner mg.co.za,valke.co.za##.widget_banners phonedog.com##.widget_bar_bottom bloomberg.com##.widget_bb_doubleclick_widget thescore.com##.widget_bigbox usacryptocoins.com##.widget_buffercode_banner_upload_info cbslocal.com,radio.com##.widget_cbs_gamification_stats_widget lulzsec.net##.widget_chaturbate_widget styleblazer.com##.widget_fashionblog_ad urbanmusichq.se##.widget_gad extremetech.com##.widget_gptwidget fxempire.com##.widget_latest_promotions fxempire.com##.widget_latest_promotions_right geek.com##.widget_logicbuy_first_deal modamee.com##.widget_nav_menu fxempire.com##.widget_recommended_brokers twistedsifter.com##.widget_sifter_ad_bigbox_widget amygrindhouse.com,lostintechnology.com##.widget_text fxempire.com##.widget_top_brokers venturebeat.com##.widget_vb_dfp_ad wired.com##.widget_widget_widgetwiredadtile indiatvnews.com##.wids educationbusinessuk.net##.width100 > a[target="_blank"] > img educationbusinessuk.net##.width100 > p > a[target="_blank"] > img listverse.com##.wiki espn.co.uk##.will_hill oboom.com##.window_current foxsports.com##.wisfb_sponsor weatherzone.com.au##.wo-widget-wrap-1 planet5d.com##.wp-image-1573 israelnationalnews.com##.wp_HPCenterIn notjustok.com##.wpbr-widget notjustok.com,punchng.com##.wpbrbanner webpronews.com##.wpn-business-resources buzzinn.net##.wpn_finner talkers.com##.wpss_slideshow theregister.co.uk##.wptl osbot.org##.wrapper > center:nth-of-type(-n+3) > a breitbart.com##.wrapperBanner bnaibrith.org##.wsite-image[style="padding-top:10px;padding-bottom:10px;margin-left:0;margin-right:0;text-align:center"] poynter.org##.wsm_frame_medium webtoolhub.com##.wth_zad_text search.ch##.www_promobox newsherder.com##.x-300x250 davidwalsh.name##.x-terciary jpost.com##.xl-banner-wrap chronicle.com,fareastgizmos.com,ganzworld.com,webdesignerdepot.com##.xoxo cryptothrift.com##.xoxo > #text-34 cryptothrift.com##.xoxo > #text-50 cryptothrift.com##.xoxo > #text-55 mail.google.com##.xz yahoo.com##.y7-breakout-bracket yahoo.com##.y708-ad-eyebrow yahoo.com##.y708-commpartners yahoo.com##.y708-promo-middle yahoo.com##.y7moneyhound yahoo.com##.y7partners yahoo.com##.ya-LDRB yahoo.com##.ya-darla-LREC yahoo.com##.yad yahoo.com##.yad-cpa mysanantonio.com##.yahoo-bg thetimes-tribune.com##.yahoo-content_match candofinance.com,idealhomegarden.com##.yahooSl newsok.com##.yahoo_cm thetandd.com##.yahoo_content_match reflector.com##.yahooboss tumblr.com##.yamplus-unit-container yardbarker.com##.yard_leader autos.yahoo.com##.yatAdInsuranceFooter autos.yahoo.com##.yatysm-y yelp.be,yelp.ca,yelp.ch,yelp.co.nz,yelp.co.uk,yelp.com,yelp.com.au,yelp.com.sg,yelp.ie##.yelp-add finance.yahoo.com##.yfi_ad_s groups.yahoo.com##.yg-mbad-row groups.yahoo.com##.yg-mbad-row > * yelp.be,yelp.ca,yelp.ch,yelp.co.nz,yelp.co.uk,yelp.com,yelp.com.au,yelp.com.sg,yelp.ie##.yla yelp.be,yelp.ca,yelp.ch,yelp.co.nz,yelp.co.uk,yelp.com,yelp.com.au,yelp.com.sg,yelp.ie##.yloca-list yelp.be,yelp.ca,yelp.ch,yelp.co.nz,yelp.co.uk,yelp.com,yelp.com.au,yelp.com.sg,yelp.ie##.yloca-search-result local.yahoo.com##.yls-rs-paid eurosport.yahoo.com##.yom-sports-betting finance.yahoo.com,news.yahoo.com##.yom-ysmcm yellowpages.aol.com##.yp_ad yahoo.com##.yschspns yahoo.com##.ysm-cont travel.yahoo.com##.ysmcm yahoo.com##.ysptblbdr3 travel.yahoo.com##.ytrv-lrec nfl.com##.yui3-polls-mobile-adspot maps.yahoo.com##.yui3-widget-stacked zvents.com##.z-spn-featured mail.google.com##.z0DeRc zacks.com##.zacks_header_ad_ignore zap2it.com##.zc-station-position cricketcountry.com##.zeeibd downturk.net##.zippo israelnationalnews.com##.znn foodprocessorsdirect.com##.zoneWidth100 tomsguide.com,tomshardware.com##.zonepub yfrog.com##.zoom-promotion-bottom isearch.whitesmoke.com##:not(.item):not(.stats) + * + .item ogsi.it##A[href^="//adbit.co/?a=Advertise"] cryptocoinsnews.com##A[onclick^="_gaq.push(['_trackEvent', 'Ads',"] fastpiratebay.eu,thepiratebay.se##A[title="Anonymous Download "] mobilephonetalk.com##[align="center"] > b > a[href^="http://tinyurl.com/"] incredimail.com##[autoid="sponsoredLinks"] bittorrent.am##[bgcolor="#66CCCC"][style="background: rgb(126, 180, 224)"] facebook.com##[data-referrer="pagelet_side_ads"] hulu.com##[flashvars^="backgroundURL=http://ads.hulu.com/published/"] bunalti.com##[height="90"][width="728"] facebook.com##[href^="/ads/adboard/"] forums.motortrend.com##[id^="IN_HOUSE_AD_SWITCHER_"] explosm.net##[id^="MarketGid"] cultofmac.com##[name="dn-frame-1"] naturalblaze.com##[rel="nofollow"][href^="http://products.naturalblaze.com/"] > img google.com,~mail.google.com##[style="border: 1px solid rgb(0, 90, 136);"] google.com,~mail.google.com##[style="border: 1px solid rgb(145, 117, 77);"] google.com,~mail.google.com##[style="border: 1px solid rgb(241, 250, 248);"] google.com,~mail.google.com##[style="border: 1px solid rgb(51, 102, 153);"] google.com,~mail.google.com##[style="border: 1px solid rgb(51, 102, 204);"] timeanddate.com##[style="float: right; width: 170px;"] condo.com##[style="float:left;width:515px;"] hindustantimes.com##[style="font-family:Arial; color: #545454; font-size:10px; font-family:Arial; padding-right:15px"] netload.in##[style="height: 100px;"] notalwaysright.com##[style="height: 250px; text-align: center; margin-bottom:20px"] wxyz.com##[style="height:310px;width:323px"] uploaded.to##[style="margin-left: 15px;"] crazymotion.net##[style="margin: 10px auto 0pt; width: 875px;"] wahm.com##[style="min-height:250px;"] narutoforums.com##[style="padding:0px 0px 6px 0px"] > div[style="padding:0px 0px 0px 0px;margin-top:4px;"] darelease.com,latestdown.com##[style="width: 100%; margin: 0pt auto;"] tecca.com##[style="width:728px; height:90px;"] blockchain.info##[style="width:728px;overflow:hidden;margin:0px auto;max-width:90%;"] p2pnet.net##[target="_blank"] ewallpapers.eu##[title="Advertising"] marketwatch.com##[width="120"][bgcolor="#d7d7d6"] torrentresource.com##[width="150"]:last-child ewallpapers.eu##[width="160"] urlfan.com##[width="160px"] boyplz.com##[width="250"] break.com##[width="300"][height="250"] capitolfax.com##[width="410"] td[width="50%"]:first-child 4chan.org,crackdump.com##[width="468"] majorgeeks.com##[width="478"][height="70"] 4chan.org##[width="728"] timeanddate.com##[width="728"][height="90"] crackdump.com##[width="74"] empireonline.com##[width="950"][height="130"][align="center"] lindaikeji.blogspot.com##a > img[height="600"] powerbot.org##a > img[width="729"] facebook.com##a[ajaxify^="/ajax/emu/end.php?"] bitcointalk.org##a[class^="td_headerandpost"][href^="https://www.privateinternetaccess.com"] pcmag.com##a[data-section="Ads"] linksave.in##a[href$="speed"] filenuke.com,sharesix.com##a[href*="&popunder"] isearch.whitesmoke.com##a[href*="&rt=gp&"] filenuke.com,sharesix.com##a[href*="&zoneid="] huffingtonpost.com##a[href*=".atwola.com/"] imgah.com##a[href*=".com/track/"] mangafox.me##a[href*=".game321.com/"] in5d.com,jeffbullas.com,siteworthchecker.com##a[href*=".hop.clickbank.net"] hotbollywoodactress.net##a[href*=".makdi.com"] sportinglife.com##a[href*=".skybet.com/"] punjabimob.org##a[href*=".smaato.net"] iolproperty.co.za##a[href*="/Ad_Click_Thru.jsp?"] dutchnews.nl##a[href*="/adbanners/"] itweb.co.za,radiofrontier.ch##a[href*="/adclick.php?"] business-standard.com##a[href*="/adclicksTag.php?"] itweb.co.za##a[href*="/adredir.php?"] bitcoinist.net##a[href*="/adserv/click.php?id="] f1today.net##a[href*="/advertorial--"] adlock.org##a[href*="/download/"] videobull.to##a[href*="/go-to-watch.php"] rapidok.com##a[href*="/go/"] devshed.com##a[href*="/www/delivery/"] ietab.net##a[href*="/xadnet/"] ultimate-guitar.com##a[href*="=http://www.jamplay.com/"] encyclopediadramatica.se##a[href*="http://torguard.net/aff.php"] inamsoftwares.com##a[href=" http://60ads.com"] watch-movies-az.com##a[href="../download_video.php"] unitconversion.org##a[href="../noads.html"] encyclopediadramatica.se##a[href="//encyclopediadramatica.se/sparta.html"] insidefacebook.com##a[href="/advertise"] fooooo.com##a[href="/bannerClickCount.php"] opensubtitles.org##a[href="/en/aoxwnwylgqtvicv"] gtplanet.net##a[href="/geo-GT6-preorder.php"] viewdocsonline.com##a[href="/links/regboost_header.php"] mailinator.com##a[href="/soget.jsp"] dlldll.com##a[href="/stw_lp/fmr/"] thejointblog.com##a[href="http://42grow.com"] > img dogepay.com##a[href="http://WeSellDoges.com"] > img addgadgets.com##a[href="http://addgadgets.com/mcafee-internet-security/"] thejointblog.com##a[href="http://autoseeds.com/"] > img vivaprograms.com##a[href="http://b6384502.linkbucks.com"] mediafire4u.com##a[href="http://bit.ly/lFerdB"] internet-online.org##a[href="http://bn6us.etvcorp.track.clicksure.com"] delishows.com##a[href="http://delishows.com/stream.php"] crackdb.cd##a[href="http://directdl.com"] crackdb.cd##a[href="http://down.cd/"] onhax.net##a[href="http://downloadlink.onhax.net"] encyclopediadramatica.es##a[href="http://encyclopediadramatica.es/webcamgirls.html"] tny.cz##a[href="http://followshows.com?tp"] tf2maps.net##a[href="http://forums.tf2maps.net/payments.php"] generalfiles.me##a[href="http://gofindmedia.net/"] search.yahoo.com##a[href="http://help.yahoo.com/l/us/yahoo/search/basics/basics-03.html"] digitallydownloaded.net##a[href="http://iphone.qualityindex.com/"] > img bazoocam.org##a[href="http://kvideo.org"] datafilehost.com##a[href="http://liversely.net/datafileban"] maketecheasier.com##a[href="http://maketecheasier.com/advertise"] limetorrents.cc##a[href="http://movie4u.org/"] moviefather.com##a[href="http://moviefather.com/watchonline.php"] mp3truck.net##a[href="http://mp3truck.net/get-torrent/"] my.rsscache.com##a[href="http://nimbb.com"] soft32.com##a[href="http://p.ly/regbooster"] ultimate-guitar.com##a[href="http://plus.ultimate-guitar.com/ad-free/"] infowars.com##a[href="http://prisonplanet.tv/"] forum.ihubhost.net##a[href="http://proleaks.com"] propakistani.pk##a[href="http://propakistani.pk/sms/"] clashbot.org##a[href="http://rsmalls.com"] > img gooddrama.net##a[href="http://spendcrazy.net"] adrive.com##a[href="http://stores.ebay.com/Berkeley-Communications-Corporation"] uniladmag.com##a[href="http://thetoiletstore.bigcartel.com/"] toucharcade.com##a[href="http://toucharcade.com/sdlink/"] toucharcade.com##a[href="http://toucharcade.com/sdlink2/"] toucharcade.com##a[href="http://toucharcade.com/sdlink3/"] rlsbb.com##a[href="http://trailerhell.com/make_money.html"] freetv.tv##a[href="http://tvoffer.etvcorp.track.clicksure.com"] vidbear.com##a[href="http://videoworldx.com"] watch-movies-az.com##a[href="http://watch-movies-az.com/download_video1.php"] bangtidy.net##a[href="http://www.bangtidy.net/AFF.php"] bangtidy.net##a[href="http://www.bangtidy.net/mrskin.php"] betterhostreview.com##a[href="http://www.betterhostreview.com/arvixe.com"] betterhostreview.com##a[href="http://www.betterhostreview.com/hosting-review-bluehost.htm"] activistpost.com##a[href="http://www.bloggersecret.com/"] thejointblog.com##a[href="http://www.bombseeds.nl/"] > img hscripts.com##a[href="http://www.buildmylink.com"] desivideonetwork.com##a[href="http://www.desiaction.com"] diablo3builds.com##a[href="http://www.diablo3builds.com/bc"] dirwell.com##a[href="http://www.dirwell.com/submit.php"] dllerrors-fix.com##a[href="http://www.dllerrors-fix.com/Download.php"] dl4all.com##a[href="http://www.enginesong.com"] iphonecake.com##a[href="http://www.filepup.net/get-premium.php"] interupload.com##a[href="http://www.fileserving.com/"] filmon.tv##a[href="http://www.filmon.com"] geocities.ws##a[href="http://www.gridhoster.com/?geo"] financialsurvivalnetwork.com##a[href="http://www.hardassetschi.com/"] thejointblog.com##a[href="http://www.herbiesheadshop.com/"] > img scam.com##a[href="http://www.ip-adress.com/trace_email/"] wiiuiso.com##a[href="http://www.jobboy.com"] nichepursuits.com##a[href="http://www.longtailpro.com"] makeuseof.com##a[href="http://www.makeuseof.com/advertise/"] megatorrent.eu##a[href="http://www.megatorrent.eu/go2.html"] dailymirror.lk##a[href="http://www.nawaloka.com/"] nichepursuits.com##a[href="http://www.nichepursuits.com/whp"] nichepursuits.com##a[href="http://www.nichewebsitetheme.com"] naijaborn.com##a[href="http://www.njorku.com/nigeria"] > img ps3iso.com##a[href="http://www.pcgameiso.com"] letmesingthis.com##a[href="http://www.singorama.me"] animenova.tv,animetoon.tv,gogoanime.com,goodanime.eu,gooddrama.net,toonget.com##a[href="http://www.spendcrazy.net"] gogoanime.com,goodanime.eu##a[href="http://www.spendcrazy.net/"] dosplash.com##a[href="http://www.sverve.com/dashboard/DoSplash"] talkarcades.com##a[href="http://www.talkarcades.com/misc.php?do=page&template=advertise"] telepisodes.net##a[href="http://www.telepisodes.net/downloadtvseries.php"] thejointblog.com##a[href="http://www.thebestsalvia.com/"] > img free-wallpaper-download.com##a[href="http://www.thoosje.com/toolbar.html"] sitevaluecalculator.com##a[href="http://www.top-site-list.com"] quicksilverscreen.com##a[href="http://www.tubeplus.com"] thejointblog.com##a[href="http://www.unitedforcare.org/sign_up"] > img thejointblog.com##a[href="http://www.uptowngrowlab.net/"] > img vidbux.com##a[href="http://www.vidbux.com/ccount/click.php?id=4"] vivaprograms.com##a[href="http://www.vivausb.com"] watchop.com##a[href="http://www.watchop.com/download.php"] ziddu.com##a[href="http://wxdownloadmanager.com/zdd/"] zmea-log.blogspot.com##a[href="http://zmea-log.blogspot.com/p/rapids-for-sale.html"] wemineall.com,wemineltc.com##a[href="https://diceliteco.in"] namepros.com##a[href="https://uniregistry.com/"] vpsboard.com##a[href="https://vpsboard.com/advertise.html"] ugotfile.com##a[href="https://www.astrill.com/"] cryptocoinsnews.com##a[href="https://www.genesis-mining.com/pricing"] 300mbmovies4u.com##a[href^="//1phads.com/"] doubleclick.net##a[href^="//dp.g.doubleclick.net/apps/domainpark/"] rapidog.com##a[href^="/adclick.php"] sweflix.net,sweflix.to##a[href^="/adrotate.php?"] shroomery.org##a[href^="/ads/ck.php?"] metrolyrics.com##a[href^="/ads/track.php"] shroomery.org##a[href^="/ads/www/delivery/"] scoop.co.nz##a[href^="/adsfac.net/link.asp?"] facebook.com##a[href^="/ajax/emu/end.php?"] icmag.com##a[href^="/banners.php?"] rsbuddy.com##a[href^="/campaign/click_"] business-standard.com##a[href^="/click-tracker/textlink/"] torrentbit.net##a[href^="/click/9/"] hpcwire.com##a[href^="/ct/e/"] torrentfunk.com##a[href^="/dltor3/"] merdb.ru,primewire.ag##a[href^="/external.php?gd=0&"] yourbittorrent.com##a[href^="/extra/"] vitorrent.net##a[href^="/file.php?name"] tinydl.eu##a[href^="/go.php?http://sharesuper.info"] yourbittorrent.com##a[href^="/go/"] bts.ph##a[href^="/goto_.php?"] downloadhelper.net##a[href^="/liutilities.php"] houndmirror.com,sharedir.com##a[href^="/out.php?"] torrentproject.se##a[href^="/out3/"] torrentproject.org,torrentproject.se##a[href^="/out4/"] airliners.net##a[href^="/rad_results.main?"] ahashare.com##a[href^="/re.php?url"] torrentv.org##a[href^="/rec/"] trashortreasure.co.nz##a[href^="/rotator1/click.php?"] torrent.cd,torrentdb.in,torrentz.cd##a[href^="/site/sp/"] torrentfunk.com##a[href^="/tor2/"] torrentfunk.com##a[href^="/tor3/"] stuff.co.nz##a[href^="/track/click/"] bitsnoop.com##a[href^="/usenet_dl/"] bitsnoop.com##a[href^="/usenet_dl/"] + br + span rarbg.to,rarbgmirror.com,rarbgproxy.com##a[href^="/wd_adpub.php?"] torrentz.ch,torrentz.com,torrentz.eu,torrentz.li,torrentz.me,torrentz.ph##a[href^="/z/ddownload/"] torrents.de,torrentz.ch,torrentz.com,torrentz.eu,torrentz.in,torrentz.li,torrentz.me,torrentz.ph##a[href^="/z/webdownload/"] womenspress.com##a[href^="Redirect.asp?UID="] 474747.net##a[href^="ad"] xbox-hq.com##a[href^="banners.php?"] xtshare.com##a[href^="download.php?download="] downloadhelper.net##a[href^="free-driver-scan.php"] sockshare.com##a[href^="fuu.php"] rom-freaks.net##a[href^="gotomirror-"] coolsport.tv##a[href^="http://188.95.48.110/"] thefilebay.com##a[href^="http://91.205.157.43/"] heroturko.org##a[href^="http://MyDownloadHQ.com/index.asp?PID="] newssun.com##a[href^="http://access.newssun.com/b_cl.php?"] activistpost.com##a[href^="http://activistpost.net/"] > img bayfiles.com##a[href^="http://ad.propellerads.com/"] unawave.de##a[href^="http://ad.zanox.com/"] reading107fm.com,three.fm##a[href^="http://adclick.g-media.com/"] jdownloader.org##a[href^="http://adcolo.com/ad/"] extremefile.com##a[href^="http://adf.ly/"] highdefjunkies.com##a[href^="http://adorama.evyy.net/"] depositfiles.com,dfiles.eu##a[href^="http://ads.depositfiles.com/"] gorillavid.in##a[href^="http://ads.gorillavid.in/"] hindilinks4u.to##a[href^="http://ads.hindilinks4u.to/"] howproblemsolution.com##a[href^="http://ads.howproblemsolution.com/"] hardwareheaven.com##a[href^="http://adserver.heavenmedia.com/"] deviantart.com##a[href^="http://advertising.deviantart.com/"] thesearchenginelist.com##a[href^="http://affiliate.buy.com/gateway.aspx?"] smallbusinessbrief.com##a[href^="http://affiliate.wordtracker.com/"] the-numbers.com##a[href^="http://affiliates.allposters.com/"] freebetcodes.info##a[href^="http://affiliates.galapartners.co.uk/"] justhungry.com##a[href^="http://affiliates.jlist.com/"] news24.com##a[href^="http://affiliates.trafficsynergy.com/"] animetake.com##a[href^="http://anime.jlist.com/click/"] torrent-invites.com##a[href^="http://anonym.to?http://www.seedmonster.net/clientarea/link.php?id="] speedvideo.net##a[href^="http://api.adlure.net/"] datafilehost.com,load.to,tusfiles.net##a[href^="http://applicationgrabb.net/"] avxhome.se##a[href^="http://avaxnews.net/tags/"] webmail.co.za##a[href^="http://b.wm.co.za/click.pwm?"] extratorrent.cc,extratorrent.unblocked.pw,extratorrentlive.com##a[href^="http://bestories.xyz/"] thetvdb.com##a[href^="http://billing.frugalusenet.com/"] coinad.com,digitallydownloaded.net,dotmmo.com,ebookw.com,fastvideo.eu,majorgeeks.com,ncrypt.in,rapidvideo.org,sh.st,ultshare.com##a[href^="http://bit.ly/"] ancient-origins.net##a[href^="http://bit.ly/"] > img bitminter.com##a[href^="http://bitcasino.io?ref="] leasticoulddo.com##a[href^="http://blindferret.clickmeter.com/"] lowyat.net##a[href^="http://bs.serving-sys.com"] demonoid.pw,torrentfreak.com,torrents.de,torrentz.in,torrentz.li,torrentz.me,torrentz.ph##a[href^="http://btguard.com/"] nexadviser.com##a[href^="http://budurl.com/"] downforeveryoneorjustme.com,isup.me##a[href^="http://bweeb.com/"] akeelwap.net,w2c.in##a[href^="http://c.admob.com/"] zomganime.com##a[href^="http://caesary.game321.com/"] ebooksx.org##a[href^="http://castee.com/"] spacemov.com##a[href^="http://cdn.adsrvmedia.net/"] adexprt.com##a[href^="http://cdn3.adexprts.com"] + span animenewsnetwork.com##a[href^="http://cf-vanguard.com/"] vidstatsx.com##a[href^="http://channelpages.com/"] commitstrip.com##a[href^="http://chooseyourboss.com/?utm_source="] quuit.com##a[href^="http://classic.thumbplay.com/join/"] akeelwap.net##a[href^="http://click.buzzcity.net/click.php?"] weddingmuseum.com##a[href^="http://click.linksynergy.com/"] topsocial.info##a[href^="http://click.search123.uk.com/"] videomide.com##a[href^="http://click.wapdollar.in/"] mp3-shared.net##a[href^="http://click.yottacash.com?PID="] unawave.de##a[href^="http://clix.superclix.de/"] heraldscotland.com,tmz.com##a[href^="http://clk.atdmt.com/"] 180upload.com##a[href^="http://clkmon.com/static/rdr.html?pid="] stream2watch.com##a[href^="http://clkrev.com/adServe/"] absoluteradio.co.uk,mkfm.com##a[href^="http://clkuk.tradedoubler.com/click?"] dot-bit.org##a[href^="http://coinabul.com/?a="] gas2.org##a[href^="http://costofsolar.com/?"] powvideo.net##a[href^="http://creative.ad127m.com/"] idm-crack-patch.com##a[href^="http://databass.info"] armslist.com##a[href^="http://delivery.tacticalrepublic.com/"] ebookw.com##a[href^="http://dlguru.com/"] dllnotfound.com##a[href^="http://dllnotfound.com/scan.php"] majorgeeks.com##a[href^="http://download.iobit.com/"] free-tv-video-online.me##a[href^="http://downloaderfastpro.info/"] filegag.com##a[href^="http://downloadsave.info/"] letstalkbitcoin.com##a[href^="http://easypress.ca/?V="] > img infowars.com##a[href^="http://efoodsdirect.sitescout.com/click?clid="] ucas.com##a[href^="http://eva.ucas.com/s/redirect.php?ad="] flashvids.org##a[href^="http://flashvids.org/click/"] forumpromotion.net##a[href^="http://freebitco.in/?r="] extratorrent.cc,uploadrocket.net##a[href^="http://getsecuredfiles.com/"] extratorrent.cc##a[href^="http://getterstory.com/"] kinox.to,speedvideo.net,thepiratebay.to##a[href^="http://go.ad2up.com/"] mangahere.com##a[href^="http://go.game321.com/"] filesoup.com##a[href^="http://gomediamasteronline.com/"] armorgames.com,getios.com,myrls.se,ncrypt.in,rapidvideo.tv,theedge.co.nz##a[href^="http://goo.gl/"] ancient-origins.net##a[href^="http://goo.gl/"] > img limetorrents.cc,thepiratebay.みんな##a[href^="http://guide-free.com/"] kinox.to##a[href^="http://hd-streams.tv/"] putlocker.is##a[href^="http://hdmoviesinc.com/"] kingfiles.net##a[href^="http://hdplugin.fplayer-updates.com/"] crackdb.cd##a[href^="http://homeklondike.com"] hotfiletrend.com##a[href^="http://hotfiletrend.com/c.php?"] free-tv-video-online.me,movdivx.com,quicksilverscreen.com,veehd.com##a[href^="http://install.secure-softwaremanager.com/"] ncrypt.in,querverweis.net##a[href^="http://is.gd/"] quuit.com##a[href^="http://itunes.apple.com/"] minecraftprojects.net##a[href^="http://jmp2.am/"] fastvideo.eu,rapidvideo.org##a[href^="http://jojomedia.net/"] ebooksx.org##a[href^="http://king.gameoftraffic.com/"] knowfree.net##a[href^="http://kvors.com/click/"] whatismyip.com##a[href^="http://link.pcspeedup.com/aff_"] flight-simulators.net##a[href^="http://linknow.me/"] torrentzap.com##a[href^="http://links.torrentzap.com/go.php?"] torrentzapproxy.com##a[href^="http://links.torrentzapproxy.com/"] linksave.in##a[href^="http://linksave.in/go/uhnl/"] linksave.in##a[href^="http://linksave.in/go/unnl/"] linksave.in##a[href^="http://linksave.in/go/usene/"] linksave.in##a[href^="http://linksave.in/go/usn/"] linuxforums.org##a[href^="http://linuxforums.tradepub.com/"] warriorforum.com##a[href^="http://list-mob.com/"] > img d-h.st,datafilehost.com,torlock.com,torrentfunk.com,yourbittorrent.com##a[href^="http://liversely.com/"] do2dear.net,mhktricks.net##a[href^="http://liversely.net/"] uploadrocket.net##a[href^="http://livesetwebs.org/"] d-h.st##a[href^="http://lp.sharelive.net/"] psnprofiles.com##a[href^="http://manage.aff.biz/"] isohunt.to,unlimitzone.com##a[href^="http://masteroids.com/"] megauploadsearch.net##a[href^="http://megauploadsearch.net/adv.php"] justhungry.com##a[href^="http://moe.jlist.com/click/"] thejointblog.com##a[href^="http://movieandmusicnetwork.com/content/cg/"] > img moviearchive.eu##a[href^="http://moviearchive.sharingzone.net/"] crackdb.cd##a[href^="http://mp3menu."] rlsbb.com##a[href^="http://netload.in/index.php?refer_id="] mobilust.net##a[href^="http://nicevid.net/?af="] mp3db.ru##a[href^="http://novafile.com/premium"] blasternation.com##a[href^="http://ox.fenixm.com/www/delivery/ck.php?"] mail.google.com##a[href^="http://pagead2.googlesyndication.com/"] azcentral.com##a[href^="http://phoenix.dealchicken.com/"] vr-zone.com##a[href^="http://pikachu.vr-zone.com.sg/"] kewlshare.com##a[href^="http://pointcrisp.com/"] projectfreetv.ch##a[href^="http://projectfreetv.ch/adblock/"] crackdb.cd##a[href^="http://promoddl.com"] decadeforum.com,downdlz.com,downeu.org,serials.ws##a[href^="http://pushtraffic.net/TDS/?wmid="] vodly.to##a[href^="http://r.lumovies.com/"] boingboing.net##a[href^="http://r1.fmpub.net/?r="] search.certified-toolbar.com##a[href^="http://redir.widdit.com/redir/?"] > * toolsvoid.com##a[href^="http://ref.name.com/"] nextofwindows.com##a[href^="http://remotedesktopmanager.com/?utm_source="] hardwareheaven.com##a[href^="http://resources.heavenmedia.net/click_through.php?"] richkent.com##a[href^="http://richkent.com/uses/"] thejointblog.com##a[href^="http://sensiseeds.com/refer.asp?refid="] > img share-links.biz##a[href^="http://share-links.biz/redirect/"] search.com##a[href^="http://shareware.search.com/click?"] merdb.ru##a[href^="http://shineads.net/"] filetie.net##a[href^="http://softwares2015.com/"] thejointblog.com##a[href^="http://speedweed.com/_clicktracker.php?code="] > img uvnc.com##a[href^="http://sponsor2.uvnc.com"] uvnc.com##a[href^="http://sponsor4.uvnc.com/"] ipdb.at##a[href^="http://strongvpn.com/aff/"] 5x.to##a[href^="http://support.suc-team.info/aff.php"] majorgeeks.com##a[href^="http://systweak.com/"] your-pagerank.com##a[href^="http://te-jv.com/?r="] strata40.megabyet.net##a[href^="http://tiny.cc/freescan"] serialbase.us,serialzz.us##a[href^="http://tinyurl.com"] kinox.to,ncrypt.in,wtso.net##a[href^="http://tinyurl.com/"] sockshare.com##a[href^="http://toolkitfreefast.com/"] encyclopediadramatica.es,encyclopediadramatica.se##a[href^="http://torguard.net/"] fastvideo.eu,rapidvideo.org##a[href^="http://toroadvertisingmedia.com/"] catmo.ru##a[href^="http://torrentindex.org/"] mangafox.me##a[href^="http://track.games.la/"] lolking.net##a[href^="http://track.strife.com/?"] iwatchonline.to##a[href^="http://tracking.aunggo.com/"] cryptocoinsnews.com##a[href^="http://tracking.coin.mx/aff_c?offer_id="] lmgtfy.com##a[href^="http://tracking.livingsocial.com/aff_c?"] hipfile.com##a[href^="http://tracktrk.net/?"] imageporter.com##a[href^="http://trw12.com/"] ugotfile.com##a[href^="http://ugotfile.com/affiliate?"] israbox.com##a[href^="http://urmusiczone.com/signup?"] pandaapp.com##a[href^="http://vda.gtarcade.com/?q="] videobull.com##a[href^="http://videobull.com/wp-content/themes/videozoom/go.php?"] videobull.com##a[href^="http://vtgtrk.com/"] wakingtimes.com##a[href^="http://wakingtimes.com/ads/"] videomide.com##a[href^="http://wapdollar.in/"] bitminter.com##a[href^="http://wbf.go2cloud.org/aff_c?offer_id="] webdesignshock.com##a[href^="http://www.123rf.com"] serials.ws,uptobox.com##a[href^="http://www.1clickmoviedownloader.net/"] 300mbfilms.com##a[href^="http://www.300mbfilms.com/ads/"] distrowatch.com##a[href^="http://www.3cx.com/"] movie4u.org##a[href^="http://www.4kmoviesclub.com/signup?"] cio-today.com##a[href^="http://www.accuserveadsystem.com/accuserve-go.php?c="] distrowatch.com##a[href^="http://www.acunetix.com/"] babelzilla.org##a[href^="http://www.addonfox.com/"] printroot.com##a[href^="http://www.adgz.net/"] jordantimes.com##a[href^="http://www.aigcmiddleast.com/ads"] thehackernews.com##a[href^="http://www.alienvault.com/"] distrowatch.com##a[href^="http://www.amazon."][href*="/obidos/ASIN/"] absoluteradio.co.uk##a[href^="http://www.amazon."][href*="creativeASIN"] absoluteradio.co.uk,cloudfront.net,dailypaul.com,desktoplinuxreviews.com,jimlynch.com,mkfm.com,policestateusa.com,quuit.com,songfacts.com##a[href^="http://www.amazon."][href*="tag="] urgrove.com##a[href^="http://www.amoninst.com/"] hqwallpapers4free.com##a[href^="http://www.anno1777.com/index.php?i="] macdailynews.com##a[href^="http://www.anrdoezrs.net/click-"] publicradio.org##a[href^="http://www.arkivmusic.com/classical/Playlist?&source="] dumbassdaily.com##a[href^="http://www.badjocks.com"] bitcoinukforum.com##a[href^="http://www.betcoinpartners.com/"] freetv-video.ca##a[href^="http://www.bhmfinancial.com/"] bingo-hunter.com##a[href^="http://www.bingo3x.com/main.php"] rghost.net##a[href^="http://www.binverse.com"] freebitco.in##a[href^="http://www.bitcoininsanity.com/affiliates/"] filesoup.com##a[href^="http://www.bitlord.com/"] filesoup.com##a[href^="http://www.bitlordsearch.com/"] bitlordsearch.com##a[href^="http://www.bitlordsearch.com/bl/fastdibl.php?"] freebitcoins.nx.tc,getbitcoins.nx.tc##a[href^="http://www.bitonplay.com/create?refCode="] usenet-crawler.com##a[href^="http://www.cash-duck.com/"] gsmarena.com##a[href^="http://www.cellpex.com/affiliates/"] onlinefreetv.net##a[href^="http://www.chitika.com/publishers/apply?refid="] ciao.co.uk##a[href^="http://www.ciao.co.uk/ext_ref_call.php"] cryptothrift.com##a[href^="http://www.coinographic.com/"] majorgeeks.com##a[href^="http://www.compatdb.org/"] crackdb.cd##a[href^="http://www.crackcrew.com/"] feed-the-beast.com##a[href^="http://www.creeperhost.net/aff.php?aff="] blackhatlibrary.net##a[href^="http://www.darkexile.com/forums/index.php?action=affiliates"] serials.ws##a[href^="http://www.dl-provider.com/"] dlh.net##a[href^="http://www.dlh.net/advs/www/delivery/ck.php?"] downloadhelper.net##a[href^="http://www.downloadhelper.net/do-goto-site.php?url=http%3A%2F%2Fwww.shareasale.com"] pdf-giant.com,watchseries.biz,yoddl.com##a[href^="http://www.downloadprovider.me/"] thesearchenginelist.com##a[href^="http://www.dpbolvw.net/click-"] bootstrike.com,dreamhosters.com,howtoblogcamp.com##a[href^="http://www.dreamhost.com/r.cgi?"] sina.com##a[href^="http://www.echineselearning.com/"] betterhostreview.com##a[href^="http://www.elegantthemes.com/affiliates/"] professionalmuscle.com##a[href^="http://www.elitefitness.com/g.o/"] internetslang.com##a[href^="http://www.empireattack.com"] linksave.in##a[href^="http://www.endwelt.com/signups/add/"] lens101.com##a[href^="http://www.eyetopics.com/"] mercola.com##a[href^="http://www.fatswitchbook.com/"] > img rapidvideo.org##a[href^="http://www.filmsenzalimiti.co/"] omegleconversations.com##a[href^="http://www.freecamsexposed.com/"] liveleak.com##a[href^="http://www.freemake.com/"] linksave.in##a[href^="http://www.gamesaffiliate.de/"] bootstrike.com##a[href^="http://www.gog.com/en/frontpage/?pp="] bingo-hunter.com##a[href^="http://www.harrysbingo.co.uk/index.php"] rapidvideo.tv##a[href^="http://www.hdvid-codecs.com/"] htcsource.com##a[href^="http://www.htcsimunlock.com/"] vidxden.com##a[href^="http://www.ilivid.com/vidxden_download_video.htm?"] guns.ru##a[href^="http://www.impactguns.com/cgi-bin/affiliates/"] uploadrocket.net##a[href^="http://www.insta-cash.net/"] softpedia.com##a[href^="http://www.iobit.com/"] macdailynews.com,softpedia.com##a[href^="http://www.jdoqocy.com/click-"] ps3iso.com##a[href^="http://www.jobboy.com/index.php?inc="] macdailynews.com,thesearchenginelist.com,web-cam-search.com##a[href^="http://www.kqzyfj.com/click-"] hotbollywoodactress.net##a[href^="http://www.liposuctionforall.com/"] mhktricks.net##a[href^="http://www.liversely.net/"] livescore.cz##a[href^="http://www.livescore.cz/go/click.php?"] majorgeeks.com##a[href^="http://www.majorgeeks.com/compatdb"] emaillargefile.com##a[href^="http://www.mb01.com/lnk.asp?"] sing365.com##a[href^="http://www.mediataskmaster.com"] megatorrent.eu##a[href^="http://www.megatorrent.eu/tk/file.php?q="] htmlgoodies.com##a[href^="http://www.microsoft.com/click/"] infowars.com##a[href^="http://www.midasresources.com/store/store.php?ref="] quicksilverscreen.com##a[href^="http://www.movies-for-free.net"] pixhost.org##a[href^="http://www.mydownloader.net/pr/"] 2x4u.de##a[href^="http://www.myfreecams.com/?baf="] wonkette.com##a[href^="http://www.newsmax.com?promo_code="] netmarketshare.com##a[href^="http://www.ns8.com?"] kaaz.eu##a[href^="http://www.offersfair.com/"] obfuscatorjavascript.info##a[href^="http://www.oplata.info/"] aol.com##a[href^="http://www.opselect.com/ad_feedback/"] distrowatch.com##a[href^="http://www.osdisc.com/"] shareplace.org,yourfiles.to##a[href^="http://www.pc-bodyguard.com/?p="] majorgeeks.com##a[href^="http://www.pctools.com/"] jpupdates.com##a[href^="http://www.perfectautony.com"] > img pinknews.co.uk##a[href^="http://www.pinknews.co.uk/clicks/"] internetslang.com##a[href^="http://www.pointlesssites.com"] myway.com##a[href^="http://www.popswatter.com/?partner="] primewire.ag##a[href^="http://www.primewire.ag/ab_play/"] bestgore.com##a[href^="http://www.punishtube.com/"] publichd.se##a[href^="http://www.putdrive.com/?"] mg-rover.org##a[href^="http://www.quotezone.co.uk/SetAffiliate.php?aid="] sharesix.com##a[href^="http://www.reduxmediia.com/"] majorgeeks.com##a[href^="http://www.reimageplus.com/includes/router_land.php"] tweaking.com##a[href^="http://www.reimageplus.com/includes/router_land.php?"] rpg.net##a[href^="http://www.rpg.net/ads/"] gruntig.net,jpupdates.com##a[href^="http://www.sellmilesnow.com"] > img oss.oetiker.ch##a[href^="http://www.serverscheck.com/sensors?"] blogengage.com##a[href^="http://www.shareasale.com/"] wpdailythemes.com##a[href^="http://www.shareasale.com/r.cfm?b="] > img bestgore.com##a[href^="http://www.slutroulette.com/"] findsounds.com##a[href^="http://www.soundsnap.com/search/"] leecher.to##a[href^="http://www.stargames.com/bridge.asp"] telegraph.co.uk##a[href^="http://www.telegraph.co.uk/sponsored/"] egigs.co.uk##a[href^="http://www.ticketswitch.com/cgi-bin/web_finder.exe"] audiforums.com##a[href^="http://www.tirerack.com/affiliates/"] mailinator.com##a[href^="http://www.tkqlhce.com/"] limetor.net,limetorrents.cc,limetorrents.co,torrentdownloads.cc##a[href^="http://www.torrentindex.org/"] tri247.com##a[href^="http://www.tri247ads.com/"] tsbmag.com##a[href^="http://www.tsbmag.com/wp-content/plugins/max-banner-ads-pro/"] tvduck.com##a[href^="http://www.tvduck.com/graboid.php"] tvduck.com##a[href^="http://www.tvduck.com/netflix.php"] linuxformat.com##a[href^="http://www.ukfast.co.uk/linux-jobs.html/#utm_source="] ultimate-guitar.com##a[href^="http://www.ultimate-guitar.com/goto.php"] ultimate-guitar.com##a[href^="http://www.ultimate-guitar.com/show.php?"] ultimate-guitar.com##a[href^="http://www.ultimate-guitar.com/xtra/"] codecguide.com,downloadhelper.net,dvdshrink.org,thewindowsclub.com##a[href^="http://www.uniblue.com/"] distrowatch.com##a[href^="http://www.unixstickers.com/"] israbox.com##a[href^="http://www.urmusiczone.com/signup?"] thejointblog.com##a[href^="http://www.vapornation.com/?="] > img exashare.com##a[href^="http://www.video1404.info/"] thejointblog.com##a[href^="http://www.weedseedshop.com/refer.asp?refid="] > img womenspress.com##a[href^="http://www.womenspress.com/Redirect.asp?"] wptmag.com##a[href^="http://www.wptmag.com/promo/"] israbox.net,silvertorrent.org,watchonlinefree.tv##a[href^="http://www.yourfilezone.com/"] youtube.com##a[href^="http://www.youtube.com/cthru?"] free-tv-video-online.me,muchshare.net##a[href^="http://wxdownloadmanager.com/"] datafilehost.com##a[href^="http://zilliontoolkitusa.info/"] yahoo.com##a[href^="https://beap.adss.yahoo.com/"] landofbitcoin.com##a[href^="https://bitcasino.io?ref="] bitcoinreviewer.com##a[href^="https://bitcoin-scratchticket.com/?promo="] blockchain.info##a[href^="https://blockchain.info/r?url="] > img bitcointalk.org##a[href^="https://cex.io/"] activistpost.com##a[href^="https://coinbase.com/?r="] deconf.com##a[href^="https://deconf.com/out/"] landofbitcoin.com##a[href^="https://localbitcoins.com/?ch="] conservativetribune.com,mindsetforsuccess.net##a[href^="https://my.leadpages.net/"] unblockt.com##a[href^="https://nordvpn.com/pricing/"] search.yahoo.com##a[href^="https://search.yahoo.com/search/ads;"] bitminter.com##a[href^="https://wbf.go2cloud.org/aff_c?offer_id="] leo.org##a[href^="https://www.advertising.de/"] cryptocoinsnews.com##a[href^="https://www.anonibet.com/"] bitminter.com##a[href^="https://www.cloudbet.com/en/?af_token="] escapefromobesity.net##a[href^="https://www.dietdirect.com/rewardsref/index/refer/"] avxhome.se##a[href^="https://www.nitroflare.com/payment?webmaster="] xscores.com##a[href^="https://www.rivalo1.com/?affiliateId="] youtube.com##a[href^="https://www.youtube.com/cthru?"] krapps.com##a[href^="index.php?adclick="] essayscam.org##a[id^="banner_"] m.youtube.com##a[onclick*="\"ping_url\":\"http://www.google.com/aclk?"] software182.com##a[onclick*="sharesuper.info"] titanmule.to##a[onclick="emuleInst();"] titanmule.to##a[onclick="installerEmule();"] platinlyrics.com##a[onclick^="DownloadFile('lyrics',"] checkpagerank.net##a[onclick^="_gaq.push(['_trackEvent', 'link', 'linkclick'"] zoozle.org##a[onclick^="downloadFile('download_big', null,"] zoozle.org##a[onclick^="downloadFile('download_related', null,"] coinurl.com,cur.lv##a[onclick^="open_ad('"] hugefiles.net##a[onclick^="popbi('http://go34down.com/"] hugefiles.net##a[onclick^="popbi('http://liversely.com/"] kingfiles.net##a[onclick^="window.open('http://lp.ilividnewtab.com/"] kingfiles.net##a[onclick^="window.open('http://lp.sharelive.net/"] w3schools.com##a[rel="nofollow"] nixiepixel.com##a[rel^="http://bit.ly/"] bitcointalk.org##a[style$=";width:700px;"] activistpost.com##a[style="clear: right; float: right; margin-bottom: 0em; margin-left: 1em;"] torrenticity.com##a[style="color:#05c200;text-decoration:none;"] urbandictionary.com##a[style="display: block; width: 300px; height: 500px"] billionuploads.com##a[style="display: inline-block;width: 728px;margin: 25px auto -17px auto;height: 90px;"] bitcointalk.org##a[style="text-decoration:none; display:inline-block; "] lifewithcats.tv##a[style="width: 318px; height: 41px; padding: 0px; left: 515px; top: 55px; opacity: 1;"] easyvideo.me,playbb.me,playpanda.net,video66.org,videofun.me,videowing.me,videozoo.me##a[style^="display: block;"] bitcointalk.org##a[style^="display: inline-block; text-align:left; height: 40px;"] betfooty.com##a[target="_blank"] > .wsite-image[alt="Picture"] thepiratebay.se##a[target="_blank"] > img:first-child thejointblog.com##a[target="_blank"][href="http://smokecartel.com/"] herold.at##a[target="_blank"][href="http://www.adaffix.com"] letstalkbitcoin.com##a[target="_blank"][href="http://www.edandethan.com"] > img letstalkbitcoin.com##a[target="_blank"][href="http://www.madmoneymachine.com"] > img gbatemp.net##a[target="_blank"][href="http://www.nds-card.com"] > img herold.at##a[target="_blank"][href="http://www.reise-hero.com/"] herold.at##a[target="_blank"][href="http://www.urlauburlaub.at"] noscript.net##a[target="_blank"][href^="/"] mic.com##a[target="_blank"][href^="/click?"] wg-gesucht.de##a[target="_blank"][href^="http://affiliate.immobilienscout24.de/go.cgi?pid="] thefinancialbrand.com##a[target="_blank"][href^="http://bit.ly/"] bitcoinfees.com##a[target="_blank"][href^="http://bitcoinkamikaze.com/ref/"] > img rcgroups.com##a[target="_blank"][href^="http://decals.rcgroups.com/adclick.php?bannerid="] freedomhacker.net##a[target="_blank"][href^="http://freedomhacker.net/out/"] > img thepiratebay.se##a[target="_blank"][href^="http://thepiratebay."][href*="&ad="] mmobomb.com##a[target="_blank"][href^="http://www.mmobomb.com/link/"] gbatemp.net##a[target="_blank"][href^="http://www.nds-card.com/ProShow.asp?ProID="] > img bitcoinexaminer.org##a[target="_blank"][href^="https://www.itbit.com/?utm_source="] > img noscript.net##a[target="_blаnk"][href$="?MT"] bodymindsoulspirit.com##a[target="_new"] > img hookedonads.com##a[target="_top"][href="http://www.demilked.com"] > img baymirror.com,bt.mojoris.in,getpirate.com,kuiken.co,livepirate.com,mypiratebay.cl,noncensuram.info,piraattilahti.org,pirateproxy.net,pirateproxy.se,pirateshit.com,proxicity.info,proxybay.eu,thepiratebay.gg,thepiratebay.lv,thepiratebay.se,thepiratebay.se.coevoet.nl,tpb.ipredator.se,tpb.jorritkleinbramel.nl,tpb.piraten.lu,tpb.pirateparty.ca,tpb.rebootorrents.com,unblock.to##a[title="Anonymous Download"] lordtorrent3.ru##a[title="Download"] watch-series.ag,watch-tv-series.to,watchseries.ph##a[title="Sponsored"] torfinder.net,vitorrent.org##a[title="sponsored"] bitcointalk.org##a[title^="LuckyBit"] herold.at##a[title^="Werbung: "][target="_blank"] irrigator.com.au##advertisement onlinemoviewatchs.com##b[style^="z-index: "] creatives.livejasmin.com##body norwsktv.com##body > #total just-dice.com##body > .wrapper > .container:first-child dansdeals.com##body > a[target="_blank"] > img sitevaluecalculator.com##body > center > br + a[target="_blank"] > img fancystreems.com##body > div > a primewire.ag##body > div > div[id][style^="z-index:"]:first-child movie2k.tl##body > div > div[style^="height: "] atdee.net,drakulastream.eu,magnovideo.com,movie2k.tl,sockshare.ws,streamhunter.eu,videolinkz.us,vodly.to,watchfreeinhd.com,zuuk.net##body > div > div[style^="z-index: "] ha.ckers.org##body > div:first-child > br:first-child + a + br + span[style="color:#ffffff"] viooz.co##body > div:first-child > div[id][style]:first-child www.google.com##body > div[align]:first-child + style + table[cellpadding="0"][width="100%"] > tbody:only-child > tr:only-child > td:only-child delishows.com##body > div[id] > div[id][style] > div[style] primeshare.tv##body > div[style="display:block !important;"] > div[style^="height: "] da.feedsportal.com##body > iframe + script + table[align="center"][valign="middle"] domains.googlesyndication.com##body > table:first-child + table domains.googlesyndication.com##body > table:first-child + table + table domains.googlesyndication.com##body > table:first-child > tbody:first-child > tr:first-child > td:first-child > table:first-child + table domains.googlesyndication.com##body > table:first-child > tbody:first-child > tr:first-child > td:first-child > table:first-child + table + table jguru.com##center nzbindex.com,nzbindex.nl##center > a > img[style="border: 1px solid #000000;"] cryptocoinsnews.com##center > a[href="https://xbt.social"] proxyserver.asia##center > a[href^="http://goo.gl/"][target="_blank"] 4shared.com##center[dir="ltr"] ehow.com##center[id^="DartAd_"] forumswindows8.com##center[style="font-size:15px;font-weight:bold;margin-left:auto; margin-right:auto;"] helenair.com##dd filepuma.com##dd[style="padding-left:3px; width:153px; height:25px;"] search.mywebsearch.com##div > div[style="padding-bottom: 12px;"] filenuke.com,sharesix.com##div > p:first-child + div cdrlabs.com##div[align="center"] bleachanime.org##div[align="center"][style="font-size:14px;margin:0;padding:3px;background-color:#f6f6f6;border-bottom:1px solid #ababab;"] thelakewoodscoop.com##div[align="center"][style="margin-bottom:10px;"] newhavenregister.com##div[align="center"][style="margin-top:10px;min-height:100px;"] sicilyintheworld.com##div[align="right"][bold][font\:][padding\:] alternet.org##div[aria-labelledby="ui-dialog-title-altsocial_splash"] + .ui-widget-overlay filecrop.com##div[class$="160_600"] filecrop.com##div[class$="728_90"] search.yahoo.com##div[class*="prod_listings_"] facebook.com##div[class="ego_column _5qrt"] facebook.com##div[class="ego_column _8_9"] facebook.com##div[class="ego_column pagelet _5qrt _1snm"] facebook.com##div[class="ego_column pagelet _5qrt _y92 _1snm"] facebook.com##div[class="ego_column pagelet _5qrt _y92"] facebook.com##div[class="ego_column pagelet _5qrt"] facebook.com##div[class="ego_column pagelet _y92 _5qrt _1snm"] facebook.com##div[class="ego_column pagelet _y92 _5qrt"] facebook.com##div[class="ego_column pagelet _y92"] facebook.com##div[class="ego_column pagelet"] facebook.com##div[class="ego_column"] kinox.to##div[class^="Mother_"][style^="display: block;"] anime1.com,animefreak.tv##div[class^="a-filter"] drama.net##div[class^="ad-filter"] manaflask.com##div[class^="ad_a"] greatandhra.com##div[class^="add"] u00p.com##div[class^="adv-box"] hattrick.org##div[class^="bannerBackground"] ragezone.com##div[class^="bannerBox"] plsn.com##div[class^="clickZone"] webhostingtalk.com##div[class^="flashAd_"] ragezone.com##div[class^="footerBanner"] avforums.com##div[class^="takeover_box_"] linuxbsdos.com##div[class^="topStrip"] yttalk.com##div[class^="toppedbit"] realmadrid.com##div[data-ads-block="desktop"] wayn.com##div[data-commercial-type="MPU"] monova.org##div[data-id^="http://centertrust.xyz/"] monova.org##div[data-id^="http://www.torntv-downloader.com/"] ehow.com##div[data-module="radlinks"] yahoo.com##div[data-type="ADS"] deviantart.com##div[gmi-name="ad_zone"] thetechjournal.com##div[height="250"] lastresistance.com##div[id$="FloatingBanner"] search.snapdo.com##div[id$="TopD"] wmpoweruser.com##div[id$="_ad_container"] automotive.com,internetautoguide.com,motortrend.com##div[id^="AD_CONTROL_"] topdocumentaryfilms.com##div[id^="AdAuth"] internetautoguide.com,motorcyclistonline.com##div[id^="GOOGLE_ADS_"] automotive.com##div[id^="LEADER_BOARD_"] vidspot.net##div[id^="On1Pl"] vidspot.net##div[id^="On2Pl"] nowvideo.ch##div[id^="aad"] shortlist.com##div[id^="ad-slot"] minecraftforum.net##div[id^="ad-wrapper-"] ucoz.com,ucoz.net,ucoz.org##div[id^="adBar"] chess.com##div[id^="ad_report_host_"] warframe-builder.com##div[id^="ads"] mahalo.com##div[id^="ads-section-"] streetmap.co.uk##div[id^="advert_"] askyourandroid.com##div[id^="advertisespace"] stackoverflow.com##div[id^="adzerk"] blogspot.co.nz,blogspot.com,coolsport.tv,time4tv.com,tv-link.me##div[id^="bannerfloat"] theteacherscorner.net##div[id^="catfish"] video44.net##div[id^="container_ads"] vodlocker.com##div[id^="div-gpt-ad-"] + div btsportshd.com,cricfree.eu,cricfree.sx,cricfree.tv,cricket-365.info,cricketembed.com,desihd.net,desistreams.tv,embed247.com,eplhome.com,hdfooty.tv,hqiframes.com,hqsport.tv,ihdsports.com,micast.tv,mybeststream.xyz,online--soccer.eu,premier--streams.info,putlive.in,soccerembed.com,streamking.org,twentysport.com,usachannels.tv,zuuk.net##div[id^="floatLayer"] eventhubs.com##div[id^="google_ads_"] volokh.com##div[id^="google_ads_div_"] wg-gesucht.de##div[id^="listAdPos_"] cool-sport.net,iwantsport.com,sport-guides.net,tykestv.eu##div[id^="ltas_overlay_"] proz.com##div[id^="proz_ad_zone_"] target.com##div[id^="rr_promo_"] vipboxeu.co##div[id^="slot"] facebook.com##div[id^="sponsoredTickerStory_"] facebook.com##div[id^="substream_"] .userContentWrapper > ._1ifo facebook.com##div[id^="substream_"] div[data-ft*="\"ei\":\""] yahoo.com##div[id^="tile-A"][data-beacon-url^="https://beap.gemini.yahoo.com/mbcsc?"] yahoo.com##div[id^="tile-mb-"] footstream.tv,leton.tv##div[id^="timer"] facebook.com##div[id^="topnews_main_stream_"] div[data-ft*="\"ei\":\""] ~images.search.yahoo.com,search.yahoo.com##div[id^="wp_bannerize-"] ~images.search.yahoo.com,search.yahoo.com##div[id^="yui_"] > span > ul[class]:first-child:last-child > li[class] ~images.search.yahoo.com,search.yahoo.com##div[id^="yui_"] > ul > .res[data-bg-link^="http://r.search.yahoo.com/_ylt="] + * div[class^="pla"] statigr.am##div[id^="zone"] 4shared.com##div[onclick="window.location='/premium.jsp?ref=removeads'"] gsprating.com##div[onclick="window.open('http://www.nationvoice.com')"] viphackforums.net##div[onclick^="MyAdvertisements.do_click"] ncrypt.in##div[onclick^="window.open('http://www.FriendlyDuck.com/AF_"] rapidfiledownload.com##div[onclick^="window.open('http://www.rapidfiledownload.com/out.php?"] ncrypt.in##div[onclick^="window.open('http://www2.filedroid.net/AF_"] rs-catalog.com##div[onmouseout="this.style.backgroundColor='#fff7b6'"] easyvideo.me,playbb.me,playpanda.net,video66.org,videofun.me,videowing.me,videozoo.me##div[original^="http://byzoo.org/"] fastvideo.eu##div[style$="backgroud:black;"] > :first-child highstakesdb.com##div[style$="margin-top:-6px;text-align:left;"] imagebam.com##div[style$="padding-top:14px; padding-bottom:14px;"] epdrama.com,juzupload.com##div[style$="text-align: center; border:3px gray solid"] giantfreakinrobot.com##div[style$="transition: bottom 2s ease 0s;"] surrenderat20.net##div[style$="width: 160px; height: 600px; background: #333;"] pdf-archive.com##div[style$="width: 300px; height: 250px; float: left;"] protopage.com##div[style$="width: 770px; height: 100px;"] 4sysops.com##div[style$="width:300px; height:250px; padding: 0px 3px 3px 3px; margin-bottom: 5px"] sockshare.com##div[style*="background-color:#FFF;text-align"] sockshare.com##div[style*="background-color:white;text-align"] maxgames.com##div[style*="background-image: URL('/images/sponsor_"] thegauntlet.ca##div[style*="background-image:url('/advertisers/your-ad-here-"] invisionfree.com##div[style*="height:90px;width:728px;"] kesq.com##div[style*="width:300px; height:250px;"] inquirer.net##div[style*="width:629px;height:150px;"] tennisworldusa.org##div[style=" cursor:pointer; border:5px #333 solid; width:600px; margin:0px auto; min-height:66px; height:auto; "] answerology.com##div[style=" font-family:Verdana,Arial,Helvetica,sans-serif; font-size:8px;text-align:center;letter-spacing:2px; "] koreaherald.com##div[style=" margin:20px 0 20px 0; width:670px; height:130px; background:#f0f0f0;"] tennisworldusa.org##div[style=" position:relative; overflow:hidden; margin:0px; width:667px; color:#666; height:205px; border:1px #ddd solid; border-radius:0 0 5px 5px; background-color:#FFF;"] seattlepi.com##div[style=" width:100%; height:90px; margin-bottom:8px; float:left;"] fmr.co.za##div[style=" width:1000px; height:660px; margin: 0 auto"] ontopmag.com##div[style=" width:300px; height:250px; padding:0; margin:5px auto 0 auto;"] fitbie.com##div[style=" width:300px; height:450px; padding-bottom: 160px;"] forum.guru3d.com##div[style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 6px; PADDING-TOP: 12px"] cheapostay.com##div[style="PADDING-TOP: 0px; text-align:center; width:175px;"] nasdaq.com##div[style="align: center; vertical-align: middle;width:336px;height:250px"] splitsider.com##div[style="background-color: #c0c0c0; padding: 5px; margin-bottom: 10px;"] wral.com##div[style="background-color: #ebebeb; width: 310px; padding: 5px 3px;"] zeropaid.com##div[style="background-color: #fff; padding:10px;"] frontlinesoffreedom.com##div[style="background-color: rgb(255, 255, 255); border-width: 1px; border-color: rgb(0, 0, 0); width: 300px; height: 250px;"] countryfile.com##div[style="background-color: rgb(255, 255, 255); height: 105px; padding-top: 5px;"] videoserver.biz##div[style="background-color: white; position: absolute; border: 1px solid #000000; top: -360px; left: -370px; z-index: 0; display: block; width: 600px; height: 440px; border: 0px solid green; margin: 0px;"] fansshare.com##div[style="background-color:#999999;width:300px;height:250px;"] deviantart.com##div[style="background-color:#AAB1AA;width:300px;height:120px"] deviantart.com,sta.sh##div[style="background-color:#AAB1AA;width:300px;height:250px"] dawn.com##div[style="background-color:#EEEEE4;width:973px;height:110px;margin:auto;padding-top:15px;"] moneycontrol.com##div[style="background-color:#efeeee;width:164px;padding:8px"] search.bpath.com,tlbsearch.com##div[style="background-color:#f2faff;padding:4px"] bostonherald.com##div[style="background-color:black; width:160px; height:600px; margin:0 auto;"] fansshare.com##div[style="background-image:url(/media/img/advertisement.png);width:335px;height:282px;"] fansshare.com##div[style="background-image:url(http://img23.fansshare.com/media/img/advertisement.png);width:335px;height:282px;"] vosizneias.com##div[style="background: #DADADA; border: 1px solid gray; color: gray; width: 300px; padding: 5px; float: right; font-size: 0.8em; line-height: 1.5em; font-family: arial; margin: 10px 0 10px 20px;"] regmender.com##div[style="background: #FFFDCA;border: 1px solid #C7C7C7;margin-top:8px;padding: 8px;color:#000;"] singletracks.com##div[style="background: #fff; height: 250px; width: 300px; margin-top: 0px; margin-bottom: 10px;"] gelbooru.com##div[style="background: #fff; width: 728px; margin-left: 15px;"] skyatnightmagazine.com##div[style="background: none repeat scroll 0% 0% #B3E3FA; height: 95px; padding: 5px; margin-bottom: 5px;"] cnn.com##div[style="background: transparent url(http://i.cdn.turner.com/cnn/.element/img/3.0/video/336x280_ad.gif) no-repeat scroll left top; height:304px; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;"] sternfannetwork.com##div[style="background: white; padding: 10px; margin: 10p\a \a x auto; border: 1px solid black; border-radius: 10px;"] backstage.com##div[style="background:#666666; height:250px; color:#fff;"] zeropaid.com##div[style="background:#eee;padding:5px;height:140px;clear:both;"] mamiverse.com##div[style="background:#f7f7f7;padding:40px;"] hints.macworld.com##div[style="border-bottom: 2px solid #7B7B7B; padding-bottom:8px; margin-bottom:5px;"] greatgirlsgames.com##div[style="border-bottom:1px dotted #CCC;margin:3px 0 3px 0;color:#000;padding:0 0 1px 0;font-size:11px;text-align:right;"] nytimes.com##div[style="border: 0px #000000 solid; width:300px; height:250px; margin: 0 auto"] nytimes.com##div[style="border: 0px #000000 solid; width:728px; height:90px; margin: 0 auto"] hugefiles.net##div[style="border: 0px solid black; width:728px;"] kijiji.ca##div[style="border: 1px solid #999; background: #fff"] cookingforengineers.com##div[style="border:0px solid #FFFFA0;width:160px;height:600px;"] videosbar.com##div[style="border:1px solid #EEEEEE; display:block; height:270px; text-align:center; width:300px; overflow:hidden;"] videosbar.com##div[style="border:1px solid #EEEEEE; display:block; height:270px; text-align:center; width:300px;"] undsports.com##div[style="border:1px solid #c3c3c3"] mocpages.com##div[style="border:1px solid #dcdcdc; width:300px; height:250px"] exchangerates.org.uk##div[style="border:1px solid #ddd;background:#f0f0f0;padding:10px;margin:10px 0;"] whatson.co.za##div[style="border:solid 10px #ffffff;width:125px;height:125px;"] vietnamnews.vn##div[style="clear: both;text-align: center;margin-bottom:10px;height:230px;width:300px;"] moviecarpet.com##div[style="clear:both; width:100%; padding:30px; height:250px"] staradvertiser.com##div[style="clear:both; width:292px; line-height:1.5em; padding:5px; border:5px solid #ddd;"] iconseeker.com##div[style="clear:both;width: 728px; height:90px; margin:5px auto; overflow:hidden;"] iconseeker.com##div[style="clear:both;width: 728px; height:90px; margin:5px auto;"] synonyms.net##div[style="color:#666666;font-size:10px;\""] autonews.com##div[style="color:#666666;font-size:11px;font-style:italic;text-align:right;"] christiantoday.com##div[style="color:#666666;font-size:8pt;text-align:right;"] teamforge.net##div[style="display: block; margin: 0.5em 1.5em; padding: 1em; border-style: solid;\a \9 border-color: #F0FFFF; border-width: 3px; background-color: #F0F0F0; font-size: xx-small; text-align: left;"] bumpshack.com##div[style="display: block; padding:5px 0px 5px 0px;"] free-iqtest.net##div[style="display: block; width: 800px; height: 120px; margin: 0 auto; text-align: center;"] lolking.net##div[style="display: inline-block; width: 300px; height: 250px; background: #000;"] lolking.net##div[style="display: inline-block; width: 728px; height: 90px; background: #000;"] listentoyoutube.com##div[style="display: inline-block; width: 728px; height: 90px; overflow: hidden;"] cheapoair.com,onetravel.com##div[style="display: table; width: 1px; height:1px; position:relative; margin-left:auto; margin-right:auto; text-align: center; margin-top:10px; padding: 12px; padding-bottom:5px; background-color: #e7e7e7 ! important;"] forum.xda-developers.com##div[style="display:block; margin-top:20px; margin-left:10px; width:750px; height:100px; float:left;"] veervid.com##div[style="display:block; width:302px; height:275px;"] skyweather.com.au##div[style="display:block;height:250px;width:300px;margin-bottom:20px;"] chami.com##div[style="display:inline-block; text-align:left; border-left:1px solid #eee;border-right:1px solid #eee; width:342px;padding:10px;"] lse.co.uk##div[style="display:inline;float:right;width:300px;height:250px;margin:5px 10px 15px 15px;"] mp3juices.com##div[style="float: left; font-size: 12pt; padding-top: 7px;"] bonniegames.com##div[style="float: left; height: 90px; width: 728px; background:#DDDDDD; margin:2px;"] moneymakergroup.com##div[style="float: left; margin: 1px;"] > a[href^="http://www.moneymakergroup.com/redirect.php?url="] moneymakergroup.com##div[style="float: left; margin: 1px;"]:last-child civil.ge##div[style="float: left; text-align: center; border: solid 1px #efefef; width: 320px; height: 90px;"] usedcars.com##div[style="float: left; width: 263px; text-align: center; vertical-align: top"] upi.com##div[style="float: left; width: 300px; height: 250px; overflow: hidden;"] sgclub.com##div[style="float: left; width: 310px; height: 260px;"] boarddigger.com##div[style="float: left; width: 320px; height: 250px; padding: 5px;"] dreammoods.com##div[style="float: left; width: 350; height: 350"] ps3hax.net##div[style="float: left;margin: 12px;"] apa.az##div[style="float: left;width:516px;height:60px;"] hyperlinkcode.com##div[style="float: right; margin-left: 20px; border: 1px solid #FFFFFF; background: #FFFFFF; padding: 5px;"] trendir.com##div[style="float: right; margin-left: 30px; font-size: 10px;"] linuxquestions.org##div[style="float: right; margin-left: 5px; margin-bottom: 5px; margin-top: -3px; margin-right: -3px"] cinestar.to##div[style="float: right; margin-top: 12px"] shanghaiexpat.com##div[style="float: right; width: 242px; height: 148px; cursor: pointer; "] foxsports540.com##div[style="float: right; width: 260px; height: 230px;"] bitrebels.com##div[style="float: right; width: 336px; height: 19px; text-align: right; padding-top: 4px; margin-top: -23px;"] dreammoods.com##div[style="float: right; width: 350; height: 358"] bit-tech.net##div[style="float: right; width: 728px; height: 90px; overflow: hidden; position: relative; top: 10px;"] lightreading.com##div[style="float: right; width: 728px; height: 90px;"] longislandpress.com##div[style="float:left; clear:left; margin:10px 20px 5px 0px;"] pardaphash.com##div[style="float:left; margin-left:17px; width:970px; height:28px; border:0px solid #ededed; margin-bottom:20px; background-color:#ededed; "] pardaphash.com##div[style="float:left; margin-left:17px; width:970px; height:90px; border:0px solid #ededed; margin-bottom:20px; background-color:#ededed; padding:1px;"] eaglerising.com##div[style="float:left; margin:16px 13px 0 0; width:300px; height:250px; border:thin solid #555;"] celebuzz.com##div[style="float:left; padding:30px 0 0 0; height:250px; width:300px;"] abjusa.com##div[style="float:left; position:relative; width:1000px; background:url(images/bar-t-1000.gif) top left no-repeat; padding-top:10px; margin-top:10px;"] yuku.com##div[style="float:left; width: 300px; margin-left: 10px;border: 1px solid #CCC;margin-top:10px; margin-bottom:10px;"] sitespeedlab.com##div[style="float:left; width: 336px;"] pinknews.co.uk##div[style="float:left; width:160px;"] wbur.org##div[style="float:left; width:260px; margin:15px 0 0 40px; font-family:Arial, Helvetica, sans-serif; font-size:11px; color:#999;"] 2dopeboyz.com##div[style="float:left; width:300px; height:250px;"] x64bitdownload.com##div[style="float:left; width:300px; padding-bottom:10px;font-size:92%;"] arabianoilandgas.com,arabiansupplychain.com,constructionweekonline.com,digitalproductionme.com,utilities-me.com##div[style="float:left; width:300px; padding-right:20px; padding-bottom:20px; padding-top:20px;"] amazines.com##div[style="float:left; width:341; height:285;"] top4download.com##div[style="float:left; width:620px;height:250px;clear:both;"] happynews.com##div[style="float:left; width:768px; height:90px; margin-bottom:12px;"] iconarchive.com##div[style="float:left;border:0px solid #dddddd;width:300px;height:280px;margin:3px 3px 3px 40px;"] thespoof.com##div[style="float:left;clear:left;margin-right:8px;margin-top:10px;width:338px;height:282px;"] thespoof.com##div[style="float:left;clear:left;margin-right:8px;width:200px;height:1em;"] lse.co.uk##div[style="float:left;display:inline;width:300px;height:250px;overflow:hidden;margin-bottom:10px;"] golivewire.com##div[style="float:left;height:292px;width:355px;background-image: url(http://img.golivewire.com/stickynote.gif);background-repeat: no-repeat;background-position: 0px 3px;align-text:center;padding-left:26px;padding-top:26px;"] coolios.net##div[style="float:left;line-height:23px;font-size:10px;"] listal.com##div[style="float:left;margin-right:10px;width:336px;height:280px;"] thedailyheap.com##div[style="float:left;padding:12px 12px 6px 0px;margin:0;"] cinemablend.com##div[style="float:left;width:160px;height:600px;"] cinemablend.com##div[style="float:left;width:160px;height:606px;"] visordown.com##div[style="float:left;width:300px;height:250px;"] thaivisa.com##div[style="float:left;width:310px;height:275px;"] videoweed.es##div[style="float:left;width:728px; height:90px; border:1px solid #CCC; display:block; margin:20px auto; margin-bottom:0px;"] politicususa.com##div[style="float:none;margin:10px 0 10px 0;text-align:center;"] lifescript.com##div[style="float:right; margin-bottom: 10px;"] lifescript.com##div[style="float:right; margin-bottom: 10px;width:300px;"] torrentcrazy.com##div[style="float:right; margin:5px;"] etaiwannews.com,taiwannews.com.tw##div[style="float:right; padding:5px;"] honolulustreetpulse.com##div[style="float:right; width:200px;height:180px;"] itechtalk.com##div[style="float:right; width:300px; height:250px; margin-left:10px"] denverpost.com##div[style="float:right; width:300px; height:250px; margin: 0px 0px 10px 10px;"] icydk.com##div[style="float:right; width:325px; background-color:#d7e9f5; margin:10px;"] smashingapps.com##div[style="float:right;margin-left:5px;"] geekzone.co.nz##div[style="float:right;margin:15px;width:336px;height:280px;"] cinemablend.com##div[style="float:right;text-align:right;"] putme.org##div[style="float:right;width:336px;"] runningshoesguru.com##div[style="float:right;width:336px;height:280px"] hindustantimes.com##div[style="font-family:Arial; color: #545454; font-size:10px; font-family:Arial; padding-right:102px"] hindustantimes.com##div[style="font-family:Arial; color: #545454; font-size:10px; font-family:Arial; padding-right:20px"] hindustantimes.com##div[style="font-family:Arial; color: #545454; font-size:10px; font-family:Arial;"] siliconera.com##div[style="font-family:Arial;background:#ffffff none repeat scroll 0 0;float:left;text-align:center;margin:auto 0;width:570px;"] jobberman.com##div[style="font-size: 10px;text-align: center;margin: 0px auto;letter-spacing: 1px;"] techspot.com##div[style="font-size: 16px; font-weight: bold; padding: 15px 0px; line-height: 30px; text-align:center;"] winscp.net##div[style="font-size: 70%;"] ksl.com##div[style="font-size: 9px; "] nknews.org##div[style="font-size:0.8em;text-align:center;padding-bottom:2px;font-weight:normal !important;"] twitpic.com##div[style="font-size:12px;color:#cacaca;font-weight: normal;"] wallbase.cc##div[style="font-size:13px;padding:5px"] technologyreview.com##div[style="font-size:93%; color:#666666; padding-bottom:3px;"] adf.ly##div[style="height: 120px; width: 728px; font-size:10px; text-align:center; margin: 30px auto;"] clgaming.net##div[style="height: 250px; margin-top: 20px;"] techgage.com##div[style="height: 250px; width: 300px; float: right"] way2sms.com##div[style="height: 250px; width: 610px; margin-left: -5px;"] pichunter.com,rawstory.com##div[style="height: 250px;"] northcountrypublicradio.org##div[style="height: 260px; max-width: 250px; margin: 0px auto; padding: 0px;"] innocentenglish.com##div[style="height: 260px;"] babble.com##div[style="height: 263px; margin-left:0px; margin-top:5px;"] northcountrypublicradio.org##div[style="height: 272px; max-width: 250px; margin: 5px auto 10px; padding: 4px 0px 20px;"] bsplayer.com##div[style="height: 281px; overflow: hidden"] interfacelift.com##div[style="height: 288px;"] losethebackpain.com##div[style="height: 290px;"] dreadcentral.com##div[style="height: 300px; width: 300px; float:right;"] espn.go.com##div[style="height: 325px;"] wsj.com##div[style="height: 375px; width: 390px;"] cheatcc.com##div[style="height: 50px;"] coolest-gadgets.com,necn.com##div[style="height: 600px;"] indiatimes.com##div[style="height: 60px;width: 1000px;margin: 0 auto;"] hongkongnews.com.hk##div[style="height: 612px; width: 412px;"] thetechherald.com##div[style="height: 640px"] haaretz.com##div[style="height: 7px;width: 300px;"] revision3.com##div[style="height: 90px"] cpu-world.com##div[style="height: 90px; padding: 3px; text-align: center"] yardbarker.com##div[style="height: 90px; width: 728px; margin-bottom: 0px; margin-top: 0px; padding: 0px;z-index: 1;"] thenewage.co.za##div[style="height: 90px; width: 730px; float: left; margin: 0px;"] f-picture.net##div[style="height: 90px; width: 730px; margin: 0 auto; padding: 3px; padding-left: 10px; overflow: hidden;"] snapwidget.com##div[style="height: 90px; width: 748px; margin: 0 auto 15px;"] snapwidget.com##div[style="height: 90px; width: 756px; margin: 15px auto -15px; overflow: hidden;"] food.com##div[style="height: 96px;"] ipchecking.com##div[style="height:108px"] cosmopolitan.co.za##div[style="height:112px;width:713px"] northeasttimes.com##div[style="height:120px; width:600px;"] hyperallergic.com##div[style="height:125px; padding-top: 10px;"] ubc.ug##div[style="height:130px; width:313px; text-align:center !important;"] wcbm.com##div[style="height:1550px;width:168px;border:1px solid #ccc;overflow:auto;"] shortcuts.com##div[style="height:160px;"] globaltimes.cn##div[style="height:160px;width:250px;"] dailymirror.lk##div[style="height:200px; width:300px; font-family:Arial, Helvetica, sans-serif; font-size:13px;"] exchangerates.org.uk##div[style="height:200px;width:200px;margin:10px 0;"] vgchartz.com##div[style="height:220px; width:100%;"] ubc.ug##div[style="height:248px; width:313px; text-align:center !important;"] 12ozprophet.com##div[style="height:250px !important;width:300px !important;"] coolest-gadgets.com,gardenersworld.com##div[style="height:250px"] prospect.org##div[style="height:250px; overflow:hidden;margin-bottom:20px;"] jewishencyclopedia.com##div[style="height:250px; width:250px; margin-bottom:1em"] demogeek.com##div[style="height:250px; width:250px; margin:10px;"] northeasttimes.com##div[style="height:250px; width:300px;"] theworldwidewolf.com##div[style="height:250px; width:310px; text-align:center; vertical-align:middle; display:table-cell; margin:0 auto; padding:0;"] crowdignite.com,gamerevolution.com,sheknows.com,tickld.com##div[style="height:250px;"] thenewsnigeria.com.ng##div[style="height:250px;margin-bottom: 20px"] way2sms.com##div[style="height:250px;margin:2px 0;"] zeenews.com##div[style="height:250px;overflow:hidden;"] theawesomer.com,thephoenix.com##div[style="height:250px;width:300px;"] unexplained-mysteries.com##div[style="height:250px;width:300px;background-color:#000000"] mcndirect.com##div[style="height:250px;width:300px;font:bold 16px 'tahoma'; color:Gray; vertical-align:middle; text-align:center; border:none"] unfinishedman.com##div[style="height:250px;width:300px;margin-left:15px;"] realgm.com##div[style="height:250px;width:300px;margin: 0 0 15px 15px;"] tf2wiki.net##div[style="height:260px; width:730px; border-style:none"] cracker.com.au##div[style="height:260px;width:310px;clear:both;position:relative;"] freestockphotos.biz##div[style="height:265px; width:300px;"] finance.yahoo.com##div[style="height:265px; width:300px;margin:0pt auto;"] opensourcecms.com##div[style="height:280px; background-color:#E9EEF2;"] quickr.org##div[style="height:280px; margin-top:0px; margin-bottom:10px;"] demogeek.com##div[style="height:280px; width:336px; margin:10px;"] ghacks.net##div[style="height:280px; width:336px; margin:2px 2px; float:right;"] twowheelsblog.com##div[style="height:280px;width:350px"] golivewire.com##div[style="height:292px;margin-left:10px;background-image: url(http://img.golivewire.com/stickynote-gray.gif);background-repeat: no-repeat;background-position: 0px 3px;align-text:center;padding-left:26px;padding-top:26px;"] golivewire.com##div[style="height:292px;margin-left:10px;background-image: url(http://img.golivewire.com/stickynote.gif);background-repeat: no-repeat;background-position: 0px 3px;align-text:center;padding-left:26px;padding-top:26px;"] tribune.com.pk##div[style="height:300px"] animeflv.net##div[style="height:36px;"] hyperallergic.com##div[style="height:600px;"] cybergamer.com##div[style="height:600px;margin:15px 0 0 0;"] wincustomize.com##div[style="height:60px;margin:10px auto;width:468px"] cookingforengineers.com##div[style="height:60px;width:120px;margin:0 20px 5px 20px"] chronicleonline.com,sentinelnews.com,theandersonnews.com##div[style="height:620px;width:279px;margin:auto;margin-top:5px;background-color:#eaeaea;"] monstersandcritics.com##div[style="height:690px"] kbcradio.eu##div[style="height:70px;width:480px;"] farmville.com##div[style="height:80px;"] monstersandcritics.com##div[style="height:840px"] hithiphop.com##div[style="height:90px; padding: 2px 0; text-align:center"] phpbbhacks.com,thetechjournal.com,yopmail.com##div[style="height:90px;"] wincustomize.com##div[style="height:90px;overflow:hidden;width:728px"] cracker.com.au##div[style="height:90px;width:675px;clear:both;position:relative;"] igossip.com,zillow.com##div[style="height:90px;width:728px"] cruisecritic.com##div[style="margin-bottom: 20px"] nwanime.com##div[style="margin-bottom: 3px;margin-top:-3px; height:90px;overflow:hidden;width:728px;"] desktopnexus.com##div[style="margin-bottom: 8px; height: 250px;"] stuffpoint.com##div[style="margin-bottom:0px;margin-top:-10px"] codinghorror.com##div[style="margin-bottom:10px"] charitynavigator.org##div[style="margin-bottom:10px; font-size: 10px;"] radiotimes.com##div[style="margin-bottom:10px; position:relative;background:#f2f6fd;width:300px;"] jpopasia.com##div[style="margin-bottom:10px;"] rootzwiki.com##div[style="margin-bottom:10px;line-height:20px;margin-top:-10px;"] diamscity.com##div[style="margin-bottom:15px;width:728px;height:90px;display:block;float:left;overflow:hidden;"] intoday.in##div[style="margin-bottom:20px; clear:both; float:none; height:250px;width:300px;"] 4sysops.com##div[style="margin-bottom:20px;"] merriam-webster.com##div[style="margin-bottom:20px;margin-top:-5px !important;width:300px;height:250px;"] intoday.in##div[style="margin-bottom:20px;z-index:0; clear:both; float:none; height:250px;width:300px;"] pdf-archive.com##div[style="margin-left: -30px; width: 970px; height: 90px; margin-top: 8px; margin-bottom: 10px;"] jdpower.com##div[style="margin-left: 20px; background-color: #FFFFFF;"] foxlingo.com##div[style="margin-left: 3px; width:187px; min-height:187px;"] medicalnewstoday.com##div[style="margin-left:10px; margin-bottom:15px;"] howtomobi.com##div[style="margin-left:20px; width:336px; height:280px; float:left"] propakistani.pk##div[style="margin-right: 10px;"] propakistani.pk##div[style="margin-right: 1px;"] shouldiremoveit.com##div[style="margin-top: 0px; margin-bottom: 0px;"] ebay.com##div[style="margin-top: 15px; width: 160px; height: 600px; overflow: hidden; display: block;"] ebay.co.uk,ebay.com##div[style="margin-top: 15px; width: 160px; height: 615px; overflow: hidden; display: block;"] shouldiremoveit.com##div[style="margin-top: 20px;"] way2sms.com##div[style="margin-top: 5px; height: 90px; clear: both;"] funnycrazygames.com##div[style="margin-top: 8px;"] planetsport.com##div[style="margin-top:-1px; width: 100%; height: 90px; background-color: #fff; float: left;"] technet.microsoft.com##div[style="margin-top:0px; margin-bottom:10px"] surfline.com##div[style="margin-top:10px; width:990px; height:90px"] worstpreviews.com##div[style="margin-top:15px;width:160;height:600;background-color:#FFFFFF;"] centraloutpost.com##div[style="margin-top:16px; width:740px; height:88px; background-image:url(/images/style/cnop_fg_main_adsbgd.png); background-repeat:no-repeat; text-align:left;"] 4sysops.com##div[style="margin-top:50px;margin-bottom:20px;"] sockshare.com##div[style="margin-top:6px;display:block !important;"] fullepisode.info##div[style="margin: 0 auto 0 auto; text-align:center;"] historyextra.com##div[style="margin: 0 auto; width: 290px; height: 73px; background-color: #faf7f0;); padding: 5px; margin-bottom: 5px; clear: both; font-family: 'Playfair Display', serif;"] historyextra.com##div[style="margin: 0 auto; width: 290px; height: 90px; background-color: #faf7f0; padding: 5px; margin-bottom: 5px; clear: both; font-family: 'Playfair Display', serif;"] historyextra.com##div[style="margin: 0 auto; width: 290px; height: 90px; border-top:1px dotted #3a3a3a; border-bottom:1px dotted #3a3a3a; padding: 5px 0; margin:10px 0 10px 0; clear: both;"] ap.org##div[style="margin: 0px auto 20px; width: 728px; height: 90px"] golflink.com##div[style="margin: 0px auto; width: 728px; height: 90px;"] keprtv.com##div[style="margin: 0px; width: 300px; height: 250px"] apps.facebook.com##div[style="margin: 0px; width: 760px; height: 90px; text-align: center; vertical-align: middle;"] care2.com##div[style="margin: 10px 7px; width: 301px;"] democraticunderground.com##div[style="margin: 10px auto 10px auto; text-align: center; width: 728px; height: 90px; background-color: #e6e6e6;"] uproxx.com##div[style="margin: 15px auto; width: 728px; height: 90px;"] twitpic.com##div[style="margin: 15px auto;width:730px; height:100px;"] usedcars.com##div[style="margin: 20px 0"] shouldiremoveit.com##div[style="margin: 5px 0px 30px 0px;"] comicwebcam.com##div[style="margin: 6px auto 0;"] businessspectator.com.au##div[style="margin: auto 10px; width: 300px;"] primeshare.tv##div[style="margin: auto; width: 728px; margin-bottom: -10px;"] recipepuppy.com##div[style="margin:0 auto 10px;min-height:250px;"] desivideonetwork.com##div[style="margin:0 auto; width:300px; height:250px;"] malaysiakini.com##div[style="margin:0 auto; width:728px; height:90px;"] mangafox.me##div[style="margin:0 auto;clear:both;width:930px"] joomla.org##div[style="margin:0 auto;width:728px;height:100px;"] ontopmag.com##div[style="margin:0; width:300px; height:250px; padding:0; margin:5px auto 0 auto;"] noobpreneur.com##div[style="margin:0px 0px 10px 0px; padding:20px; background:#f9f9f9; border:1px solid #ddd; text-align:center; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px;"] synonym.com##div[style="margin:0px auto; width: 300px; height: 250px;"] 10minutemail.net##div[style="margin:10px 0; height:90px; width:728px;"] 22find.com##div[style="margin:10px auto 0;width:300px;height:320px;"] drakulastream.eu##div[style="margin:10px"] businessdictionary.com##div[style="margin:14px 0 10px 0;padding:0px;min-height:220px;"] anymaking.com##div[style="margin:15px auto; border:1px solid #ccc; width:728px; height:90px;"] whattoexpect.com##div[style="margin:15px auto;width:728px;"] xnotifier.tobwithu.com##div[style="margin:1em 0;font-weight:bold;"] thespoof.com##div[style="margin:20px 5px 10px 0;"] ipiccy.com##div[style="margin:20px auto 10px; width:728px;text-align:center;"] bonjourlife.com##div[style="margin:20px auto;width:720px;height:90px;"] bikeexchange.com.au##div[style="margin:2em 0; text-align:center;"] tek-tips.com##div[style="margin:2px;padding:1px;height:60px;"] noobpreneur.com##div[style="margin:30px 0px; padding:20px; background:#f9f9f9; border:1px solid #ddd; text-align:center; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px;"] ipaddress.com##div[style="margin:32px 0;text-align:center"] bitsnoop.com##div[style="margin:4px 0 8px 0; padding:0; width:100%; height:90px; text-align:center;"] indiatvnews.com##div[style="margin:5px 0px 20px 0px"] bikeexchange.com.au##div[style="margin:60px 0 20px 0;"] jpopasia.com##div[style="margin:auto auto; text-align:center; margin-bottom:10px; width:300px; height:280px;"] into-asia.com##div[style="margin:auto; width:728px; height:105px; margin-top:20px"] codeproject.com##div[style="margin:auto;width:728px;height:90px;margin-top:10px"] androidpolice.com##div[style="max-width:160px; height:600px; margin: 0 auto;"] dawn.com##div[style="max-width:728px;max-height:90px;text-align:center;margin:0 auto;"] channelstv.com##div[style="max-width:980px; max-height:94px"] life.time.com##div[style="min-height: 226px; clear: both"] phonearena.com##div[style="min-height: 250px"] phonearena.com##div[style="min-height: 250px; width: 300px; margin: 0 auto"] cepro.com##div[style="min-height:100px; background-color:#ebeef7; border:1px solid #dde;"] maniacdev.com##div[style="min-height:250px; margin-right:auto; margin-left:auto; width:300px;"] finance.yahoo.com##div[style="min-height:265px; _height:265px; width:300px;margin:0pt auto;"] cnn.com##div[style="min-height:270px; max-height:625px;height: 270px!important;"] tulsaworld.com##div[style="min-height:400px;"] smallnetbuilder.com##div[style="min-height:95px;"] footballleagueworld.co.uk##div[style="min-width: 728px; min-height: 90px; margin: 0 auto; text-align: center;"] pixabay.com##div[style="min-width: 960px;"] islamchannel.tv##div[style="overflow: hidden; position: relative; width: 245px; height: 183.75px;"] phonearena.com##div[style="overflow:hidden; width: 300px; height: 250px;"] dailytelegraph.com.au##div[style="overflow:hidden;width:300px;height:263px;"] search.mywebsearch.com##div[style="padding-bottom: 0px; padding-top: 0px;"] desktopnexus.com##div[style="padding-bottom: 12px; height: 250px;"] freewarefiles.com##div[style="padding-bottom:15px; padding-top:5px;"] freewarefiles.com##div[style="padding-bottom:15px;"] odili.net##div[style="padding-bottom:3px;"] mid-day.com##div[style="padding-bottom:5px; position:relative; height:250px;"] cricketnirvana.com##div[style="padding-bottom:5px;height:250px"] bitcoin-otc.com##div[style="padding-left: 10px; padding-bottom: 10px; text-align: center; font-family: Helvetica;"] beforeitsnews.com##div[style="padding-left:20px;width: 300px; height: 250px; float:left;"] youtubedoubler.com##div[style="padding-left:2px; padding-top:9px; padding-bottom:8px; margin-top:0px; background-color:lightgrey;text-align:center;margin-top:18px;"] rlslog.net##div[style="padding-left:40px;"] beforeitsnews.com##div[style="padding-right:20px; width: 300px; height: 250px; float:right;"] pt-news.org##div[style="padding-right:5px; padding-top:18px; float:left; "] magweb.com##div[style="padding-top: 15px;"] drweil.com##div[style="padding-top: 5px; width:728px; padding-bottom:10px;"] ynetnews.com##div[style="padding-top:10px;padding-bottom:10px;padding-right:10px"] podbean.com##div[style="padding-top:20px;width:336px;height:280px"] funnycrazygames.com##div[style="padding-top:2px"] thenews.com.pk##div[style="padding-top:5px;;height:95px;float:left;width:931px;background:url(images/banner_top_bg.jpg);"] thenews.com.pk##div[style="padding-top:5px;height:95px;float:left;width:931px;background:url(images/banner_top_bg.jpg);"] forums.androidcentral.com##div[style="padding-top:92px !important; "] cardschat.com##div[style="padding: 0px 0px 0px 0px; margin-top:10px;"] kewlshare.com##div[style="padding: 10px; border:1px solid #E0E0E0;"] epinions.com##div[style="padding: 15px 5px;"] funvid.hu##div[style="padding: 3px 0px 0px 26px; height: 90px; clear: both;"] shaaditimes.com##div[style="padding: 5 0 0 0px; height: 138px; text-align:center; width:780px; background: url('/imgs/top-ad-bg.gif') repeat-x left bottom; background-color:#FFF9D0;"] sevenforums.com##div[style="padding: 6px 0px 0px 0px"] roblox.com##div[style="padding: 6px 8px; background: #fff; height:183px;"] dailyfinance.com##div[style="padding: 6px; float: right; width: 242px; height: 272px;"] likecool.com##div[style="padding:0 0 0 10px;height:300px"] legacy.com##div[style="padding:0; margin:0 auto; text-align:right; width:738px;"] condo.com##div[style="padding:0px 5px 0px 5px; width:300px;"] beforeitsnews.com##div[style="padding:10px 0 10px 0;height:250px;margin-bottom:5px;"] subtitleseeker.com##div[style="padding:10px 0px 10px 0px; text-align:center; width:728; height:90px;"] standardmedia.co.ke##div[style="padding:10px; width:1200px; height:90px; "] myanimelist.net##div[style="padding:12px 0px"] listentotaxman.com##div[style="padding:2px 2px 0px 0px;height:90px;overflow:hidden;text-align:right; clear:both;"] ucatholic.com##div[style="padding:5px 0 5px 0; text-align:center"] avforums.com##div[style="padding:5px 0px 0px 0px"] usfinancepost.com##div[style="padding:5px 15px 5px 0px;"] imtranslator.net##div[style="padding:5px;margin:5px;border:1px solid #21497D;"] championsradio.com##div[style="position: absolute; left: 0px; top: 259px;"] championsradio.com##div[style="position: absolute; left: 630px; top: 283px;"] yourvideohost.com##div[style="position: absolute; width: 300px; height: 250px; margin-left: -150px; left: 50%; margin-top: -125px; top: 50%; background-color: transparent;z-index:98;"] play44.net,video44.net##div[style="position: absolute; width: 300px; height: 275px; left: 150px; top: 79px; z-index: 999;"] videobam.com##div[style="position: fixed; width: 100%; text-align: left; height: 38px; padding-bottom: 2px; background: rgb(253, 237, 167) none repeat scroll 0% 0%; top: -0.000756667px; left: 0px; font-family: Arial; font-size: 15px; border-bottom: 1px solid rgb(214, 214, 214); min-width: 700px; z-index: 2147483647;"] roundgames.com##div[style="position: relative; height: 110px;"] lbcgroup.tv##div[style="position: relative; height: 250px; width: 300px;"] ampgames.com##div[style="position: relative; height: 260px;"] educationpost.com.hk##div[style="position: relative; width: 300px; height: 280px; overflow: hidden;"] newera.com.na##div[style="position: relative; width: 620px; height: 80px;"] bestreams.net##div[style="position: relative; width: 800px; height: 440px;"] kusc.org##div[style="position: relative; width: 900px; height: 250px; left: -300px;"] vidspot.net##div[style="position: relative;"]:first-child > div[id^="O"][style]:first-child streamtuner.me##div[style="position: relative;top: -45px;"] skyvids.net,streamin.to##div[style="position: relative;width: 800px;height: 440px;"] topfriv.com##div[style="position:absolute; background:#201F1D; top:15px; right:60px; width:728px; height:90px;"] sharerepo.com##div[style="position:absolute; top:10%; left:0%; width:300px; height:100%; z-index:1;"] dubbedonline.co##div[style="position:absolute;background:#000000 URL(../image/black.gif);text-align:center;width:728px;height:410px;"] theoffside.com##div[style="position:absolute;left:10px;top:138px;width:160px;height:600px;border:1px solid #ffffff;"] i6.com##div[style="position:absolute;top: 240px; left:985px;width: 320px;"] hypable.com##div[style="position:relative; float:left; width:300px; min-height:250px; background-color:grey;"] hypable.com##div[style="position:relative; float:left; width:300px; min-height:250px;"] hypable.com##div[style="position:relative; margin:0 auto; width:100%; padding:30px 0px; text-align: center; min-height:90px;"] mmorpg.com##div[style="position:relative; margin:0px; width:100%; height:90px; clear:both; padding-top:12px; text-align:center;"] healthcastle.com##div[style="position:relative; width: 300px; height: 280px;"] opiniojuris.org##div[style="position:relative; width:300px; height:250px; overflow:hidden"] hypixel.net##div[style="position:relative; width:728px; margin: auto;"] buyselltrade.ca##div[style="position:relative;overflow:hidden;width:728px;height:90px;"] shalomtv.com##div[style="position:relative;width:468px;height:60px;overflow:hidden"] fastvideo.eu##div[style="position:relative;width:896px;height:370px;margin: 0 auto;backgroud:;"] > [id]:first-child baltimorestyle.com##div[style="text-align : center ;margin-left : auto ;margin-right : auto ;position : relative ;background-color:#ffffff;height:100px;padding-top:10px;"] notalwaysright.com##div[style="text-align: center; display: block; padding-top: 30px;"] centurylink.net##div[style="text-align: center; font-size: 11px;"] rofl.to##div[style="text-align: center; height:60px; width:468px;"] drugstore.com##div[style="text-align: center; letter-spacing: 2px; color: #999999; font-size: 6pt"] drugstore.com##div[style="text-align: center; letter-spacing: 2px; color: #999999; font-size: 6pt; padding-top: 5px"] geekstogo.com##div[style="text-align: center; min-height:250px; min-width:310px;"] ap.org##div[style="text-align: center; padding-top: 10px"] nationalreview.com##div[style="text-align: center; width: 300px; margin-right:20px; margin-borrom: 20px; float:left;"] patheos.com##div[style="text-align: center; width: 970px; height: 90px;"] dailyamerican.com##div[style="text-align:center; color:#fff; width: 234px; height: 60px; margin:0 auto;"] cheapoair.com##div[style="text-align:center; font-size:10px; color:#999; background-color:#e7e7e7;"] ticketweb.com##div[style="text-align:center; font-size:10px; color:#afafaf"] tennisearth.com##div[style="text-align:center; height:630px;"] chinadaily.com.cn##div[style="text-align:center; margin-bottom:10px; width:800px; float:left; z-index:-1;"] newser.com##div[style="text-align:center; margin:-5px 0 15px; font-size:11px;"] chicagocrusader.com,garycrusader.com##div[style="text-align:center; margin:3px; height:140px; padding-left:130px;"] canoe.ca##div[style="text-align:center; min-height:260px;"] eatingwell.com##div[style="text-align:center; min-height:90px;"] customize.org##div[style="text-align:center; padding:0px 0px 20px 0px; width: 100%; height: 90px;"] customize.org##div[style="text-align:center; padding:20px 0px 0px 0px; width: 100%; height: 90px;"] legacy.com##div[style="text-align:center; padding:2px 0 3px 0;"] nowdownload.ag,nowdownload.ch,nowdownload.co,nowdownload.ec,nowdownload.sx##div[style="text-align:center; vertical-align:middle; height:250px;"] clutchmagonline.com##div[style="text-align:center; width:300px; margin: 20px auto"] cinemablend.com##div[style="text-align:center;"] geekzone.co.nz##div[style="text-align:center;clear:both;height:20px;"] iloubnan.info##div[style="text-align:center;color:black;font-size:10px;"] techguy.org##div[style="text-align:center;height:101px;width:100%;"] theawesomer.com##div[style="text-align:center;padding:20px 0px 0px 0px;height:90px;width:100%;clear:both;"] imcdb.org##div[style="text-align:center;width:150px;font-family:Arial;"] statscrop.com##div[style="text-align:left; margin-left:5px; clear:both;"]:first-child zrtp.org##div[style="text-align:left;display:block;margin-right:auto;margin-left:auto"] carpoint.com.au##div[style="text-align:right;font-size:10px;color:#999;padding:4px;border:solid #ccc;border-width:0"] mocpages.com##div[style="vertical-align:middle; width:728; height:90; max-width:728; max-height:90; border:1px solid #888;"] neowin.net##div[style="white-space:nowrap;overflow: hidden; min-height:120px; margin-top:0; margin-bottom:0;"] politicususa.com##div[style="width: 100%; height: 100px; margin: -8px auto 7px auto;"] chron.com##div[style="width: 100%; height: 90px; margin-bottom: 8px; float: left;"] cheapassgamer.com##div[style="width: 100%; height: 90px; padding: 4px 0 4px 0"] downarchive.ws##div[style="width: 100%; margin: 0 auto;"] canadianlisted.com##div[style="width: 1000px;position: relative;height:95px"] encyclopedia.com##div[style="width: 1005px;"] watertowndailytimes.com##div[style="width: 120px; height: 240px; margin-bottom: 20px;"] croatia.org##div[style="width: 120px; text-align:center"] whatson.co.za##div[style="width: 140px; height: 470px;"] magicseaweed.com##div[style="width: 160px; background: #dddddd; padding-top: 10px"] theasiantoday.com##div[style="width: 160px; border: solid 1px #2A3694; background-color: White;"] desixpress.co.uk##div[style="width: 160px; border: solid 1px #DE0A17; background-color: White;"] vr-zone.com##div[style="width: 160px; height: 600px"] brandeating.com##div[style="width: 160px; height: 600px; overflow: visible;"] performanceboats.com##div[style="width: 160px; height: 600px;"] kidzworld.com##div[style="width: 160px; height: 617px; margin: auto;"] wrip979.com##div[style="width: 160px; height: 627px"] disclose.tv##div[style="width: 160px;"] concrete.tv##div[style="width: 180px; height: 360px; border: 1px solid white;"] porttechnology.org##div[style="width: 192px; height: 70px;"] checkip.org##div[style="width: 250px; margin-left: 25px;margin-top:10px;"] whodoyouthinkyouaremagazine.com##div[style="width: 290px; height: 100px; padding: 5px; margin-bottom: 5px; clear: both;"] mmoculture.com##div[style="width: 290px; height: 250px;"] mmoculture.com##div[style="width: 290px; height: 600px;"] skyatnightmagazine.com##div[style="width: 290px; height: 70px; background-color:#B0CCE7; padding: 5px; margin-bottom: 5px; clear: both;"] sciencefocus.com##div[style="width: 290px; height: 84px; background-color: #999; padding: 5px; margin: 0 0 5px; clear: both; line-height: 17px; float: left;"] sciencefocus.com##div[style="width: 290px; height: 84px; background-color: #999; padding: 5px; margin: 10px 0 5px; clear: both; line-height: 17px; float: left;"] sciencefocus.com##div[style="width: 290px; height: 84px; background-color: rgb(229, 223, 227); padding: 5px; margin: 10px 0pt; clear: both; line-height: 17px; float: left;"] discoverwildlife.com##div[style="width: 290px; height: 90px; background-color: #d4d4d2; padding: 5px; margin-bottom: 5px; clear: both;"] homesandantiques.com##div[style="width: 290px; height: 90px; background-color: rgb(229, 223, 227); padding: 5px; margin-bottom: 5px; clear: both;"] discoverwildlife.com##div[style="width: 290px; height: 90px; border-top:1px dotted #3a3a3a; padding: 5px 0; margin:10px 0 10px 0; clear: both;"] box10.com##div[style="width: 300px; float: left;"] hitfix.com,nba.com##div[style="width: 300px; height: 100px"] kidzworld.com##div[style="width: 300px; height: 117px; margin: auto;"] eastonline.eu##div[style="width: 300px; height: 132px; margin-bottom: 20px;margin-top: 20px;"] compasscayman.com##div[style="width: 300px; height: 155px; float: left;"] compasscayman.com##div[style="width: 300px; height: 155px;float: left;"] theonion.com##div[style="width: 300px; height: 220px; overflow: hidden;"] nba.com,patheos.com##div[style="width: 300px; height: 250px"] uvnc.com##div[style="width: 300px; height: 250px; background-color: #FFFFFF"] thefightnetwork.com##div[style="width: 300px; height: 250px; background: #000"] lolking.net##div[style="width: 300px; height: 250px; background: #000;"] buccaneers.com##div[style="width: 300px; height: 250px; background: #fff;"] djmag.ca##div[style="width: 300px; height: 250px; border: 2px solid #000;"] ecorazzi.com##div[style="width: 300px; height: 250px; float: right; margin: 0 0 15px 25px;"] marriland.com##div[style="width: 300px; height: 250px; float: right; margin: 2px;"] rockol.com##div[style="width: 300px; height: 250px; left: 650px; top: 0px;"] techfresh.net##div[style="width: 300px; height: 250px; margin-bottom: 20px;"] jerusalemonline.com##div[style="width: 300px; height: 250px; margin-left: 70px; margin-top: 10px; margin-bottom: 10px;"] fame10.com##div[style="width: 300px; height: 250px; margin: 0 auto;"] socialblade.com##div[style="width: 300px; height: 250px; margin: 0px auto 10px auto;"] pcworld.com##div[style="width: 300px; height: 250px; margin:0 auto 20px; overflow:hidden;"] looklocal.co.za##div[style="width: 300px; height: 250px; overflow: auto;"] benzinga.com,newstalk.ie,newswhip.ie##div[style="width: 300px; height: 250px; overflow: hidden;"] mbworld.org##div[style="width: 300px; height: 250px; overflow:hidden;"] ukfree.tv##div[style="width: 300px; height: 250px; padding-top: 10px"] washingtonmonthly.com##div[style="width: 300px; height: 250px; padding: 15px 50px; margin-bottom: 20px; background: #ccc;"] cbsnews.com,cbssports.com,cnn.com,gamefront.com,hernandotoday.com,highlandstoday.com,mondomedia.com,performanceboats.com,sciencedaily.com,spot.ph,synonym.com,tbo.com,vitals.com,wamu.org,way2sms.com,whatsonstage.com,wnd.com##div[style="width: 300px; height: 250px;"] compasscayman.com##div[style="width: 300px; height: 250px;float: left;"] usedcars.com##div[style="width: 300px; height: 265px"] ebay.co.uk##div[style="width: 300px; height: 265px; overflow: hidden; display: block;"] kidzworld.com##div[style="width: 300px; height: 267px; margin: auto;"] wnd.com##div[style="width: 300px; height: 600px"] socialblade.com##div[style="width: 300px; height: 600px; margin: 20px auto 10px auto;"] urbandictionary.com,wraltechwire.com##div[style="width: 300px; height: 600px;"] fropper.com##div[style="width: 300px; height:250px; margin-bottom:15px;"] liveleak.com##div[style="width: 300px; height:340px"] digitalphotopro.com##div[style="width: 300px; text-align: center;"] vitals.com##div[style="width: 300px; text-align:right"] hollywoodnews.com,wnd.com##div[style="width: 300px;height: 250px;"] wnd.com##div[style="width: 300px;height: 600px;"] babesandkidsreview.com##div[style="width: 304px; height: 280px; outline: 1px solid #808080; padding-top: 2px; text-align: center; background-color: #fff;"] cheatcc.com##div[style="width: 308px; text-align: right; font-size: 11pt;"] phonearena.com##div[style="width: 320px; height: 250px; border-top: 1px dotted #ddd; padding: 17px 20px 17px 0px;"] weaselzippers.us##div[style="width: 320px; height:600px; margin-top:190px;"] thetruthaboutguns.com,weaselzippers.us##div[style="width: 320px; height:600px;"] windows7download.com##div[style="width: 336px; height:280px;"] wellness.com##div[style="width: 336px; padding: 0 0 0 15px; height:280px;"] theday.com##div[style="width: 468px; height: 60px; border: 1px solid #eeeeee; margin: 5px 0; clear: both;"] way2sms.com##div[style="width: 468px; height: 60px; margin-left: 140px;"] scriptcopy.com##div[style="width: 468px; height: 60px; text-align: center; display: block; margin: 0pt auto; background-color:#eee;"] mmoculture.com##div[style="width: 468px; height: 60px;"] win7dl.com##div[style="width: 570px; margin: 0 auto;"] redorbit.com##div[style="width: 700px; height: 250px; overflow: hidden;"] hiphopstan.com##div[style="width: 700px; height: 270px; margin-left: auto; margin-right: auto; clear: both;"] sharingcentre.net##div[style="width: 700px; margin: 0 auto;"] urbandictionary.com##div[style="width: 728px; height: 90px"] sporcle.com##div[style="width: 728px; height: 90px; display: block;"] secretmaryo.org##div[style="width: 728px; height: 90px; margin-left: 6px;"] passiveaggressivenotes.com##div[style="width: 728px; height: 90px; margin: 0 auto 5px; border: 1px solid #666;"] dbforums.com,fitness.com,uproxx.com##div[style="width: 728px; height: 90px; margin: 0 auto;"] businessmirror.com.ph##div[style="width: 728px; height: 90px; margin: 0px auto; margin-top: 5px;"] hurriyetdailynews.com,leoweekly.com##div[style="width: 728px; height: 90px; margin: 0px auto;"] twcenter.net##div[style="width: 728px; height: 90px; margin: 1em auto 0;"] ripoffreport.com##div[style="width: 728px; height: 90px; margin: 20px auto; overflow: hidden;"] uproxx.com##div[style="width: 728px; height: 90px; margin: 20px auto;"] mbworld.org##div[style="width: 728px; height: 90px; overflow: hidden; margin: 0px auto;"] nitroflare.com##div[style="width: 728px; height: 90px; text-align: center;"] gelbooru.com##div[style="width: 728px; height: 90px; text-align: left;"] bit-tech.net,eatliver.com,urbandictionary.com##div[style="width: 728px; height: 90px;"] itnews.com.au##div[style="width: 728px; height:90px; margin-left: auto; margin-right: auto; padding-bottom: 20px;"] bravejournal.com##div[style="width: 728px; margin: 0 auto;"] zoklet.net##div[style="width: 728px; margin: 3px auto;"] wnd.com##div[style="width: 728px;height: 90px"] f-picture.net##div[style="width: 730px; height: 90px; padding: 0px; padding-left: 10px; margin: 0px; border-style: none; border-width: 0px; overflow: hidden;"] news-panel.com##div[style="width: 730px; height: 95px;"] elitistjerks.com##div[style="width: 730px; margin: 0 auto"] quikr.com##div[style="width: 735px; height: 125px;"] freemake.com##div[style="width: 735px; height:60px; margin: 0px auto; padding-bottom:40px;"] radiosurvivor.com##div[style="width: 750px; height: 90px; border: padding-left:25px; margin-left:auto; margin-right:auto; padding-bottom: 40px; max-width:100%"] shop.com##div[style="width: 819px; border:1px solid #cccccc; "] shop.com##div[style="width: 819px; height: 124px; border:1px solid #cccccc; "] betterpropaganda.com##div[style="width: 848px; height: 91px; margin: 0; position: relative;"] mydaily.co.uk##div[style="width: 921px; opacity: 1; top: -110px;"] fscheetahs.co.za##div[style="width: 945px; padding-left: 15px; padding-right: 15px; padding-top: 20px; background-color: #FFFFFF"] nba.com##div[style="width: 958px; height: 90px; margin: 0 auto; text-align: center; "] patheos.com##div[style="width: 970px; height: 40px; margin-bottom: 10px;"] clatl.com##div[style="width: 970px; height: 76px; background-image: url('http://clatl.com/ads/loafdeals_homepage-bkgnd.png'); background-repeat: no-repeat; margin-bottom: 8px; margin-top: 8px; margin-left: auto; margin-right: auto;"] patheos.com##div[style="width: 970px; height: 90px; margin-bottom: 10px;"] cbssports.com##div[style="width: 970px; height: 90px;"] cheatcc.com##div[style="width:100%; background: #ffffff; padding-bottom: 5px;"] mondotimes.com##div[style="width:100%; height:90px; line-height:90px; text-align:left;"] wnd.com##div[style="width:100%; padding:0px; margin:0px;"]:first-child thesimsresource.com##div[style="width:100%;background:#000;"] howtoforge.com##div[style="width:100%;border-top:1px solid #CCCCCC;border-bottom:1px solid #CCCCCC;padding:4px 0 2px 0;margin-bottom:5px;height:27px;"] girlschase.com##div[style="width:100%;color:#666;text-align:center;font-size:50%;margin-top:-20px;"] zedomax.com##div[style="width:100%;height:280px;"] wattpad.com##div[style="width:100%;height:90px;text-align:center"] techcentral.ie##div[style="width:1000px; height:90px; margin:auto"] flixist.com##div[style="width:1000px; padding:0px; margin-left:auto; margin-right:auto; margin-bottom:10px; margin-top:10px; height:90px;"] newhampshire.com,unionleader.com##div[style="width:100px;height:38px;float:right;margin-left:10px"] techbrowsing.com##div[style="width:1045px;height:90px;margin-top: 15px;"] strangecosmos.com##div[style="width:120px; height:600;"] egyptindependent.com##div[style="width:120px;height:600px;"] googletutor.com##div[style="width:125px;text-align:center;"] eadt.co.uk,eveningstar.co.uk##div[style="width:134px; margin-bottom:10px;"] worldscreen.com##div[style="width:150px; height:205px; background-color:#ddd;"] worstpreviews.com##div[style="width:160;height:600;background-color:#FFFFFF;"] allthingsnow.com##div[style="width:160px; height: 600px;z-index:1;"] encyclopedia.com##div[style="width:160px; height:600px"] rantsports.com##div[style="width:160px; height:600px; float:left;"] gametracker.com##div[style="width:160px; height:600px; margin-bottom:8px; overflow:hidden;"] relationshipcolumns.com##div[style="width:160px; height:600px; margin-top:10px;"] inrumor.com##div[style="width:160px; height:600px; margin:0 0 20px 0;"] yourmindblown.com##div[style="width:160px; height:600px; padding:10px 0px;"] legitreviews.com,modernluxury.com,techgage.com##div[style="width:160px; height:600px;"] brothersoft.com##div[style="width:160px; height:600px;margin:0px auto;"] gogetaroomie.com##div[style="width:160px; height:616px;background: #ffffff; margin-top:10px; margin-bottom:10px;"] forums.eteknix.com##div[style="width:160px; margin:10px auto; height:600px;"] downloadcrew.com##div[style="width:160px;height:160px;margin-bottom:10px;"] belfasttelegraph.co.uk,wxyz.com##div[style="width:160px;height:600px;"] downloadcrew.com##div[style="width:160px;height:600px;margin-bottom:10px;"] leitesculinaria.com##div[style="width:162px; height:600px; float:left;"] leitesculinaria.com##div[style="width:162px; height:600px; float:right;"] undsports.com##div[style="width:170px;height:625px;overflow:hidden;background-color:#ffffff;border:1px solid #c3c3c3"] wantitall.co.za##div[style="width:195px; height:600px; text-align:center"] mlmhelpdesk.com##div[style="width:200px; height:200px;"] today.az##div[style="width:229px; height:120px;"] theadvocate.com##div[style="width:240px;height:90px;background:#eee; margin-top:5px;float:right;"] newzimbabwe.com##div[style="width:250px; height:250px;"] today.az##div[style="width:255px; height:120px;"] exchangerates.org.uk##div[style="width:255px;text-align:left;background:#fff;margin:15px 0 15px 0;"] linksrank.com##div[style="width:260px; align:left"] webstatschecker.com##div[style="width:260px; text-align:left"] chinadaily.com.cn##div[style="width:275px;height:250px;border:none;padding:0px;margin:0px;overflow:hidden;"] 101greatgoals.com##div[style="width:280px;height:440px;"] cinemablend.com##div[style="width:290px;height:600px;"] cinemablend.com##div[style="width:290px;height:606px;"] samoaobserver.ws##div[style="width:297px; height:130px;"] crescent-news.com,recordpub.com,state-journal.com,the-review.com##div[style="width:298px;height:298px;border:1px solid #adaaad;background-color:#f4f4f4;box-shadow:inset -2px -2px 7px rgba(0,0,0,0.16);-moz-box-shadow: inset -2px -2px 7px rgba(0,0,0,0.16);-webkit-box-shadow: inset 2px 2px 7px rgba(0,0,0,0.16);border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;overflow:hidden;"] worstpreviews.com##div[style="width:300;height:250;background-color:#FFFFFF;"] firstpost.com##div[style="width:300;height:250px;margin-bottom:10px;"] cooking.com##div[style="width:300;height:250px;position:relative;z-index:10000;"] weatherreports.com##div[style="width:300px; border: 1px solid gray;"] mensfitness.com##div[style="width:300px; height: 250px; overflow:auto;"] redflagflyinghigh.com,wheninmanila.com##div[style="width:300px; height: 250px;"] shape.com##div[style="width:300px; height: 255px; overflow:auto;"] itweb.co.za##div[style="width:300px; height: 266px; overflow: hidden; margin: 0"] jerusalemonline.com##div[style="width:300px; height: 284px; padding-top: 10px; padding-bottom: 10px; border: 1px solid #ffffff; float:right"] foxsportsasia.com##div[style="width:300px; height:100px;"] girlgames.com##div[style="width:300px; height:118px; margin-bottom:6px;"] midweek.com##div[style="width:300px; height:135px; float:left;"] encyclopedia.com,thirdage.com##div[style="width:300px; height:250px"] herplaces.com##div[style="width:300px; height:250px; background-color:#CCC;"] iskullgames.com##div[style="width:300px; height:250px; border: 2px solid #3a3524;"] videoweed.es##div[style="width:300px; height:250px; display:block; border:1px solid #CCC;"] picocent.com##div[style="width:300px; height:250px; margin-bottom: 35px;"] earthsky.org##div[style="width:300px; height:250px; margin-bottom:25px;"] gametracker.com##div[style="width:300px; height:250px; margin-bottom:8px; overflow:hidden;"] midweek.com##div[style="width:300px; height:250px; margin: 5px 0px; float:left;"] inrumor.com##div[style="width:300px; height:250px; margin:0 0 10px 0;"] funny-city.com,techsupportforum.com##div[style="width:300px; height:250px; margin:auto;"] filesfrog.com##div[style="width:300px; height:250px; overflow: hidden;"] search.ch##div[style="width:300px; height:250px; overflow:hidden"] worldtvpc.com##div[style="width:300px; height:250px; padding:8px; margin:auto"] adforum.com,alliednews.com,americustimesrecorder.com,andovertownsman.com,athensreview.com,batesvilleheraldtribune.com,bdtonline.com,chickashanews.com,claremoreprogress.com,cleburnetimesreview.com,clintonherald.com,commercejournal.com,commercial-news.com,coopercrier.com,cordeledispatch.com,corsicanadailysun.com,crossville-chronicle.com,cullmantimes.com,dailyiowegian.com,dailyitem.com,daltondailycitizen.com,derrynews.com,duncanbanner.com,eagletribune.com,edmondsun.com,effinghamdailynews.com,enewscourier.com,enidnews.com,farmtalknewspaper.com,fayettetribune.com,flasharcade.com,flashgames247.com,flyergroup.com,foxsportsasia.com,gainesvilleregister.com,gloucestertimes.com,goshennews.com,greensburgdailynews.com,heraldbanner.com,heraldbulletin.com,hgazette.com,homemagonline.com,itemonline.com,jacksonvilleprogress.com,jerusalemonline.com,joplinglobe.com,journal-times.com,journalexpress.net,kexp.org,kokomotribune.com,lockportjournal.com,mankatofreepress.com,mcalesternews.com,mccrearyrecord.com,mcleansborotimesleader.com,meadvilletribune.com,meridianstar.com,mineralwellsindex.com,montgomery-herald.com,mooreamerican.com,moultrieobserver.com,muskogeephoenix.com,ncnewsonline.com,newburyportnews.com,newsaegis.com,newsandtribune.com,niagara-gazette.com,njeffersonnews.com,normantranscript.com,opposingviews.com,orangeleader.com,oskaloosa.com,ottumwacourier.com,palestineherald.com,panews.com,paulsvalleydailydemocrat.com,pellachronicle.com,pharostribune.com,pressrepublican.com,pryordailytimes.com,randolphguide.com,record-eagle.com,register-herald.com,register-news.com,reporter.net,rockwallheraldbanner.com,roysecityheraldbanner.com,rushvillerepublican.com,salemnews.com,sentinel-echo.com,sharonherald.com,shelbyvilledailyunion.com,siteslike.com,standardmedia.co.ke,starbeacon.com,stwnewspress.com,suwanneedemocrat.com,tahlequahdailypress.com,theadanews.com,thedailystar.com,thelandonline.com,themoreheadnews.com,thesnaponline.com,tiftongazette.com,times-news.com,timesenterprise.com,timessentinel.com,timeswv.com,tonawanda-news.com,tribdem.com,tribstar.com,unionrecorder.com,valdostadailytimes.com,washtimesherald.com,waurikademocrat.com,wcoutlook.com,weatherforddemocrat.com,woodwardnews.net##div[style="width:300px; height:250px;"] snewsnet.com##div[style="width:300px; height:250px;border:0px;"] cnn.com##div[style="width:300px; height:250px;overflow:hidden;"] ego4u.com##div[style="width:300px; height:260px; padding-top:10px"] jerusalemonline.com##div[style="width:300px; height:265px;"] gogetaroomie.com##div[style="width:300px; height:266px; background: #ffffff; margin-bottom:10px;"] topgear.com##div[style="width:300px; height:306px; padding-top: 0px;"] jerusalemonline.com,race-dezert.com##div[style="width:300px; height:600px;"] worldscreen.com##div[style="width:300px; height:65px; background-color:#ddd;"] standard.co.uk##div[style="width:300px; margin-bottom:20px; background-color:#f5f5f5;"] uesp.net##div[style="width:300px; margin-left: 120px;"] miamitodaynews.com##div[style="width:300px; margin:0 auto;"] windsorite.ca##div[style="width:300px; min-height: 600px;"] forzaitalianfootball.com##div[style="width:300px; min-height:250px; max-height:600px;"] yourmindblown.com##div[style="width:300px; min-height:250px; padding:10px 0px;"] etfdailynews.com##div[style="width:300px;border:1px solid black"] egyptindependent.com##div[style="width:300px;height:100px;"] independent.com##div[style="width:300px;height:100px;margin-left:10px;margin-top:15px;margin-bottom:15px;"] snewsnet.com##div[style="width:300px;height:127px;border:0px;"] smh.com.au##div[style="width:300px;height:163px;"] 1071thez.com,classichits987.com,funnyjunk.com,indiana105.com,kgrt.com,pocket-lint.com,wakeradio.com,xrock1039.com##div[style="width:300px;height:250px"] afterdawn.com,egyptindependent.com,flyertalk.com,hairboutique.com,itnews.com.au,leftfootforward.org,news92fm.com,nfl.com,nowtoronto.com,techcareers.com,tuoitrenews.vn,wowcrunch.com##div[style="width:300px;height:250px;"] kohit.net##div[style="width:300px;height:250px;background-color:#000000;"] winrumors.com##div[style="width:300px;height:250px;background:#c0c8ce;"] ysr1560.com##div[style="width:300px;height:250px;border:1pt #444444 solid;position:relative;left:5px;"] nextpowerup.com##div[style="width:300px;height:250px;display:block;margin:20px auto;overflow:hidden"] afterdawn.com##div[style="width:300px;height:250px;float:left;"] hiphopdx.com##div[style="width:300px;height:250px;margin-bottom:20px;"] animelite.net##div[style="width:300px;height:250px;margin-left:35px;"] raaga.com##div[style="width:300px;height:250px;margin-top:5px;margin-bottom:5px;"] gossipcop.com##div[style="width:300px;height:250px;margin:0;padding:0;"] 961kiss.com##div[style="width:300px;height:250px;overflow:hidden;margin-bottom:10px;"] whatismyipaddress.com##div[style="width:300px;height:266px;clear:both;padding-top:0px;"] judgespot.com##div[style="width:300px;height:270px; line-height: 18px;border-width:0px;border-style:solid;border-color:white;padding:0px; font-size: 13px;"] amazon.ca,amazon.co.uk,amazon.com##div[style="width:300px;height:280px;"] extremefile.com##div[style="width:300px;margin-left:360px;padding-top:29px;"] reelseo.com##div[style="width:300px;min-height:250px; margin:0 auto 12px auto;"] fanpop.com##div[style="width:300px;min-height:250px;color:#999999;"] techsonia.com##div[style="width:301px;height:268px;border:1px outset blue;"] techsonia.com##div[style="width:301px;height:619px;border:1px outset blue;"] weartv.com##div[style="width:303px;background-color:#336699;font-size:10px;color:#cccccc"] newsblaze.com##div[style="width:305px;height:250px;float:left;"] houserepairtalk.com##div[style="width:305px;height:251px;"] whois.net##div[style="width:320px; float:right; text-align:center;"] tomopop.com##div[style="width:330px; overflow:hidden;"] worldtvpc.com##div[style="width:336px; height:280px; padding:8px; margin:auto"] geekzone.co.nz,standardmedia.co.ke##div[style="width:336px; height:280px;"] theepochtimes.com##div[style="width:336px;float:left;margin-right:18px"] pcadvisor.co.uk##div[style="width:336px;height:214px;font-family:Arial,sans-serif;background: url(http://www.broadbandgenie.co.uk/img/hosted/PCAdvisor/bbg-bg-336x214.jpg) no-repeat;position:relative;font-family: Arial,Helvetica,sans-serif;"] stabroeknews.com##div[style="width:336px;height:280px;"] zedomax.com##div[style="width:336px;height:280px;float:center;"] maximumpcguides.com##div[style="width:336px;height:280px;margin:0 auto"] auto-types.com##div[style="width:337px;height:280px;float:right;margin-top:5px;"] techsonia.com##div[style="width:337px;height:298px;border:1px outset blue;"] worldwideweirdnews.com##div[style="width:341px; height:285px;float:left; display:inline-block"] mapsofindia.com##div[style="width:345px;height:284px;float:left;"] keo.co.za##div[style="width:350px;height:250px;float:left;"] catholicworldreport.com##div[style="width:350px;height:275px;background:#e1e1e1;padding:25px 0px 0px 0px; margin: 10px 0;"] hostcabi.net##div[style="width:350px;height:290px;float:left"] internet.com##div[style="width:350px;margin-bottom:5px;"] internet.com##div[style="width:350px;text-align:center;margin-bottom:5px"] gamepressure.com##div[style="width:390px;height:300px;float:right;"] top4download.com##div[style="width:450px;height:205px;clear:both;"] worldscreen.com##div[style="width:468px; height:60px; background-color:#ddd;"] bfads.net##div[style="width:468px; height:60px; margin:0 auto 0 auto;"] hiphopearly.com##div[style="width:468px; height:60px; margin:5px auto;"] ualpilotsforum.org##div[style="width:468px; height:60px;"] jwire.com.au##div[style="width:468px;height:60px;margin:10px 0;"] independent.com##div[style="width:468px;height:60px;margin:10px 35px;clear:both;padding-top:15px;border-top:1px solid #ddd;"] jwire.com.au##div[style="width:468px;height:60px;margin:10px auto;"] kwongwah.com.my##div[style="width:468px;height:60px;text-align:center;margin-bottom:10px;"] kwongwah.com.my##div[style="width:468px;height:60px;text-align:center;margin:20px 0 10px;"] standardmedia.co.ke##div[style="width:470px; height:100px; margin:20px;"] southcoasttoday.com##div[style="width:48%; border:1px solid #3A6891; margin-top:20px;"] limelinx.com##div[style="width:480px; height:60px;"] weatherbug.com##div[style="width:484px; height:125px; background:#FFFFFF; overflow:hidden;"] reactiongifs.com##div[style="width:499px; background:#ffffff; margin:00px 0px 35px 180px; padding:20px 0px 20px 20px; "] classiccars.com##div[style="width:515px;border-style:solid;border-width:thin;border-color:transparent;padding-left:10px;padding-top:10px;padding-right:10px;padding-bottom:10px;background-color:#CFCAC4"] wwitv.com##div[style="width:520px;height:100px"] toorgle.net##div[style="width:550px;margin-bottom:15px;font-family:arial,serif;font-size:10pt;"] lifewithcats.tv##div[style="width:600px; height:300px;"] techgage.com##div[style="width:600px; height:74px;"] chrome-hacks.net##div[style="width:600px;height:250px;"] hiphopwired.com##div[style="width:639px;height:260px;margin-top:20px;"] insidemobileapps.com##div[style="width:648px;"] windows7download.com##div[style="width:680px;height:280px;clear:both;"] manilatimes.net##div[style="width:690px; height:90px; clear:both; margin-bottom:10px;"] mailinator.com##div[style="width:700;height:120;text-align:left;"] directmirror.com##div[style="width:700px;border: 4px solid #DDDDDD;border-radius: 4px 4px 4px 4px;padding: 10px;"] desivideonetwork.com##div[style="width:728px; float:left;"] surrenderat20.net##div[style="width:728px; height: 90px; margin: 10px auto 0px; background: #111;"] uesp.net##div[style="width:728px; height:105px; overflow: hidden; margin-left: auto; margin-right: auto;"] encyclopedia.com##div[style="width:728px; height:90px"] qvideoshare.com##div[style="width:728px; height:90px; border:1px solid #DFDFDF;"] moneycontrol.com##div[style="width:728px; height:90px; border:solid 1px #000080;"] scottishamateurfootballforum.com##div[style="width:728px; height:90px; display:inline-block;"] bangkokpost.com##div[style="width:728px; height:90px; margin-left: auto; margin-right: auto;"] relationshipcolumns.com##div[style="width:728px; height:90px; margin-top:18px;"] mustangevolution.com##div[style="width:728px; height:90px; margin: 0 auto;"] canadapost.ca##div[style="width:728px; height:90px; margin: auto; text-align: center; padding: 10px;"] gta3.com,gtagarage.com,gtasanandreas.net,myanimelist.net##div[style="width:728px; height:90px; margin:0 auto"] fas.org##div[style="width:728px; height:90px; margin:10px 0 20px 0;"] herplaces.com##div[style="width:728px; height:90px; margin:12px auto;"] motionempire.me##div[style="width:728px; height:90px; margin:20px auto 10px; padding:0;"] imgbox.com##div[style="width:728px; height:90px; margin:auto; margin-bottom:8px;"] dodgeforum.com,hondamarketplace.com##div[style="width:728px; height:90px; overflow:hidden; margin:0 auto;"] freeforums.org,scottishamateurfootballforum.com##div[style="width:728px; height:90px; padding-bottom:20px;"] alliednews.com,americustimesrecorder.com,andovertownsman.com,androidpolice.com,athensreview.com,batesvilleheraldtribune.com,bdtonline.com,boards.ie,chickashanews.com,claremoreprogress.com,cleburnetimesreview.com,clintonherald.com,commercejournal.com,commercial-news.com,cookingforengineers.com,coopercrier.com,cordeledispatch.com,corsicanadailysun.com,crossville-chronicle.com,cullmantimes.com,dailyiowegian.com,dailyitem.com,daltondailycitizen.com,derrynews.com,duncanbanner.com,eagletribune.com,edmondsun.com,effinghamdailynews.com,enewscourier.com,enidnews.com,farmtalknewspaper.com,fayettetribune.com,flyergroup.com,forzaitalianfootball.com,gainesvilleregister.com,gloucestertimes.com,goshennews.com,greensburgdailynews.com,heraldbanner.com,heraldbulletin.com,hgazette.com,homemagonline.com,itemonline.com,jacksonvilleprogress.com,joplinglobe.com,journal-times.com,journalexpress.net,kokomotribune.com,lockportjournal.com,mankatofreepress.com,mcalesternews.com,mccrearyrecord.com,mcleansborotimesleader.com,meadvilletribune.com,meridianstar.com,mineralwellsindex.com,montgomery-herald.com,mooreamerican.com,moultrieobserver.com,muskogeephoenix.com,ncnewsonline.com,newburyportnews.com,newsaegis.com,newsandtribune.com,niagara-gazette.com,njeffersonnews.com,normantranscript.com,orangeleader.com,oskaloosa.com,ottumwacourier.com,palestineherald.com,panews.com,paulsvalleydailydemocrat.com,pellachronicle.com,pharostribune.com,pressrepublican.com,pryordailytimes.com,randolphguide.com,record-eagle.com,register-herald.com,register-news.com,reporter.net,rockwallheraldbanner.com,roysecityheraldbanner.com,rushvillerepublican.com,salemnews.com,sentinel-echo.com,sharonherald.com,shelbyvilledailyunion.com,starbeacon.com,stwnewspress.com,suwanneedemocrat.com,tahlequahdailypress.com,theadanews.com,thedeadwood.co.uk,thelandonline.com,themoreheadnews.com,thesnaponline.com,tiftongazette.com,times-news.com,timesenterprise.com,timessentinel.com,timeswv.com,tonawanda-news.com,tribdem.com,tribstar.com,ualpilotsforum.org,unionrecorder.com,valdostadailytimes.com,washtimesherald.com,waurikademocrat.com,wcoutlook.com,weatherforddemocrat.com,woodwardnews.net##div[style="width:728px; height:90px;"] theepochtimes.com##div[style="width:728px; height:90px;margin:10px auto 0 auto;"] thedailystar.com##div[style="width:728px; height:90px;position: relative; z-index: 1000 !important"] highdefjunkies.com##div[style="width:728px; margin:0 auto; padding-bottom:1em"] imagebam.com##div[style="width:728px; margin:auto; margin-top:10px; margin-bottom:10px; height:90px;"] kavkisfile.com##div[style="width:728px; text-align:center;font-family:verdana;font-size:10px;"] 1500espn.com##div[style="width:728px;display:block;margin:10px auto 10px auto;height:90px;"] net-temps.com##div[style="width:728px;height:100px;margin-left:auto;margin-right:auto"] ipernity.com##div[style="width:728px;height:100px;margin:0 auto;"] tictacti.com##div[style="width:728px;height:110px;text-align:center;margin: 10px 0 20px 0; background-color: White;"] 1071thez.com,classichits987.com,indiana105.com,kgrt.com,pocket-lint.com,wakeradio.com,xrock1039.com##div[style="width:728px;height:90px"] footballfancast.com##div[style="width:728px;height:90px; margin: 0 auto 10px;"] wxyz.com##div[style="width:728px;height:90px;"] roxigames.com##div[style="width:728px;height:90px;\a border:1px solid blue;"] sualize.us##div[style="width:728px;height:90px;background:#bbb;margin:0 auto;"] dubbedonline.co##div[style="width:728px;height:90px;display:block;margin-top:10px;bottom:-10px;position:relative;"] videohelp.com##div[style="width:728px;height:90px;margin-left: auto ; margin-right: auto ;"] raaga.com##div[style="width:728px;height:90px;margin-top:10px;margin-bottom:10px"] delishows.com##div[style="width:728px;height:90px;margin:0 auto"] stopmalvertising.com##div[style="width:728px;height:90px;margin:0 auto;padding:0;text-align:center;margin-bottom:32px;"] holidayscentral.com##div[style="width:728px;height:90px;margin:15px auto;clear:both"] colorgirlgames.com##div[style="width:728px;height:90px;margin:5px auto"] neatorama.com##div[style="width:728px;height:90px;margin:5px auto;"] technabob.com##div[style="width:728px;height:90px;margin:8px 0px 16px 0px;"] colorgirlgames.com##div[style="width:728px;height:90px;margin:8px auto 8px"] maximumpcguides.com##div[style="width:728px;height:90px;position:absolute;top:-95px;left:103px;"] attheraces.com##div[style="width:728px;height:90px;text-align:center;float:left;background-color:#EFEFEF;"] interglot.com##div[style="width:728px;margin-right:auto;margin-left:auto"] putme.org##div[style="width:728px;margin:0 auto;"] solomid.net##div[style="width:728px;padding:5px;background:#000;margin:auto"] proxynova.com##div[style="width:730px; height:90px;"] usfinancepost.com##div[style="width:730px;height:95px;display:block;margin:0 auto;"] movie.to,movie4k.me,movie4k.to,movie4k.tv##div[style="width:742px"] > div[style="min-height:170px;"] > .moviedescription + br + a dawn.com##div[style="width:745px;height:90px;margin:auto;margin-bottom:20px;"] 1fichier.com##div[style="width:750px;height:110px;margin:auto"] imagebam.com##div[style="width:780px; margin:auto; margin-top:10px; margin-bottom:10px; height:250px;"] brothersoft.com##div[style="width:795px; height:95px; float:left;text-align:center;"] currency.me.uk##div[style="width:916px;border:1px solid #e1e1e1;background:#fff;padding:1px;margin-bottom:10px;"] btstorrent.so##div[style="width:930px;height:230px;margin:auto;"] tigerdirect.ca##div[style="width:936px; clear:both; margin-top:2px; height:90px;"] thegardenisland.com##div[style="width:950px; height:90px; margin:10px auto; display:block;"] uploadc.com,zalaa.com##div[style="width:950px; padding:10px;padding-bottom:0px; "] japannewsreview.com##div[style="width:955px;height:90px;align:auto;margin-bottom:10px;"] cnbc.com##div[style="width:960;height:90;margin:0 0 5px 0;"] speedmonkey.net##div[style="width:960px;height:110px;text-align:center"] thinkdigit.com##div[style="width:960px;height:90px;margin:10px auto"] back9network.com##div[style="width:976px;height:120px;text-align:center;"] tigerdirect.ca##div[style="width:977px; clear:both; margin-top:2px; height:90px;"] gametracker.com##div[style="width:980px; height:48px; margin-bottom:5px; overflow:hidden;"] apphit.com##div[style="width:980px;height:100px;clear:both;margin:0 auto;"] teleservices.mu##div[style="width:980px;height:50px;float:left; "] performanceboats.com##div[style="width:994px; height:238px;"] search.ch##div[style="width:994px; height:250px"] happystreams.net##div[style="z-index: 2000; background-image: url(\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\"); left: 145px; top: 120px; height: 576px; width: 1024px; position: absolute;"] independent.com##div[style^="background-image:url('http://media.independent.com/img/ads/ads-bg.gif')"] sevenforums.com##div[style^="border: 1px solid #94D3FE;"] gamebanshee.com##div[style^="border:1px solid #b98027; width:300px;"] interfacelift.com##div[style^="clear: both; -moz-border-radius: 6px; -webkit-border-radius: 6px;"] redbrick.me##div[style^="cursor:pointer; position: relative;width:1000px; margin: auto; height:150px; background-size:contain; "] iload.to##div[style^="display: block; width: 950px;"] google.com##div[style^="height: 16px; font: bold 12px/16px"] drakulastream.eu##div[style^="height: 35px; z-index: 99999"] rapidvideo.tv##div[style^="height: 35px;"] kingfiles.net##div[style^="height: 36px;"] animenova.tv,animetoon.tv,gogoanime.com,goodanime.eu,gooddrama.net,toonget.com##div[style^="left: "] monova.org##div[style^="padding-bottom: "] watchonlineseries.eu##div[style^="padding-top:5px;float:left;"] 300mbmovies4u.com##div[style^="padding-top:5px;float:left;width:100%;"] technabob.com##div[style^="padding:0px 0px "] easyvideo.me,playbb.me,playpanda.net,videofun.me,videowing.me,videozoo.me##div[style^="position: absolute;"] mp3juices.com##div[style^="position: fixed; width: 100%; text-align: left; height: 40px; background: none"] viz.com##div[style^="position:absolute; width:742px; height:90px;"] easyvideo.me,playbb.me,playpanda.net,video66.org,videofun.me,videowing.me,videozoo.me##div[style^="top: "] video66.org##div[style^="width: "] eatliver.com##div[style^="width: 160px; height: 600px;"] allmyvideos.net##div[style^="width: 315px; "] someimage.com##div[style^="width: 728px; height: 90px;"] kino.to##div[style^="width: 972px;display: inline;top: 130px;"] easyvideo.me,playbb.me,playpanda.net,videofun.me,videowing.me,videozoo.me##div[style^="width:"] sockshare.com##div[style^="width:302px;height:250px;"] way2sms.com##div[style^="width:728px; height:90px;"] timelinecoverbanner.com##div[style^="width:728px;"] walmart.com##div[style^="width:740px;height:101px"] urgrove.com##div[style^="z-index: "] > div[style] putlocker.is,thevideos.tv##div[style^="z-index: 2000; background-image:"] nowwatchtvlive.com##div[style^="z-index: 99999; position: fixed; width: 100%;"] easyvideo.me,playbb.me,playpanda.net,videofun.me,videowing.me,videozoo.me##div[style^="z-index:"] eclipse.org##div[width="200"] isnare.com##div[width="905"] blackcatradio.biz##div[width="969"][height="282"] filepuma.com##dt[style="height:25px; text-indent:3px; padding-top:5px;"] xtremesystems.org##embed[width="728"] opensubtitles.org##fieldset > table[style="width:100%;"] > tbody > .change astatalk.com##fieldset[style="border: 1px solid #fff; margin-bottom: 15px; height: 60px; background-color: navy;"] bit.com.au,pcauthority.com.au##fieldset[style="width:98%;border:1px solid #CCC;margin:0px;padding:0px 0px 0px 5px;"] cinemablend.com##font[color="#737373"] imgburn.com,majorgeeks.com##font[face="Arial"][size="1"] bargaineering.com##font[face="Verdana"][color="#808080"] ap.org##font[size="1"][color="#999999"] realitytvworld.com##font[size="1"][color="gray"] nufc.com##font[size="1"][face="Verdana"] > table[width="297"][cellspacing="0"][cellpadding="0"][border="0"][align="center"] zippyshare.com##font[style="font-size: 10px; letter-spacing: 3px; word-spacing: 2px; line-height: 18px;"] zippyshare.com##font[style="font-size: 10px; letter-spacing: 3px; word-spacing: 2px;"] law.com,topcultured.com##h3 rapidog.com##h3[style="color:#00CC00"] virtualmedicalcentre.com##h5 bigpond.com##h5.subheading indowebster.com##h6.size_1 sketchucation.com##h6[style^="width:766px;height:88px;"] forums.eteknix.com##hgroup[style="width:728px; margin:10px auto; height:90px;"] discovermagazine.com##hr[size="1"] bangfiles.net##iframe[height="210px"] thepiratebay.se##iframe[height="60"] totallystressedout.com##iframe[height="600"] ziddu.com##iframe[height="80"] imgbar.net##iframe[src="earn.php"] thepiratebay.se##iframe[src^="//cdn2.adexprt.com/"] cybergamer.com##iframe[src^="http://au.cybergamer.com/iframe_cgbanners.php?"] btmon.com##iframe[style="height: 600px; width: 160px"] thestreet.com##iframe[style="margin-top:5px;"] bizjournals.com##iframe[style="width: 340px; height: 165px; overflow: hidden; padding: 10px; margin: 0px; border-style: none;"] hinduwebsite.com##iframe[style="width:320px; height:260px;"] adjet.biz##iframe[style^=" width:100%;"] wiki.answers.com##iframe[width="160px"] france24.com##iframe[width="300"][height="170"] therecord.com##iframe[width="300"][height="180"] fansshare.com,shanghaidaily.com##iframe[width="300"][height="250"] wiki.answers.com##iframe[width="300px"] mouthshut.com##iframe[width="336"] nowwatchtvlive.com##iframe[width="460"] 1tvlive.in,ahashare.com,ziddu.com##iframe[width="728"] wiki.answers.com##iframe[width="728px"] shoesession.com##iframe[width="732"] gamecopyworld.com##iframe[width="760"] newsbtc.com##img.aligncenter[width="200"][height="200"] thegremlin.co.za##img[alt*="Advertising"] chroniclelive.co.uk,liverpoolecho.co.uk##img[alt*="sponsor"] thecuttingedgenews.com##img[alt="Ad by The Cutting Edge News"] inmr.com##img[alt="Ad"] technologyreview.com,tmz.com##img[alt="Advertisement"] techxav.com##img[alt="Commercial WordPress themes"] joox.net##img[alt="Download FLV Direct"] jdownloader.org##img[alt="Filesonic Premium Download"] isohunt.to##img[alt="Free download"] onhax.net##img[alt="Full Version"] scriptmafia.org##img[alt="SM AdSpaces"] searchquotes.com##img[alt="Sponsored"] awazfm.co.uk##img[alt="advert"] warezchick.com##img[border="0"] jozikids.co.za##img[height="140"][width="140"] gametrailers.com##img[height="15"][width="300"] africandesignmagazine.com##img[height="226"] mypbrand.com##img[height="250"] africandesignmagazine.com##img[height="300"] 2pass.co.uk##img[height="470"] warez-home.net##img[height="60"][width="420"] pururin.com##img[height="600"] africandesignmagazine.com##img[height="688"] abundance-and-happiness.com,professionalmuscle.com##img[height="90"] nmap.org##img[height="90"][width="120"] airplaydirect.com,roadtester.com.au,slayradio.org##img[height="90"][width="728"] prowrestling.com##img[height="91"] modelhorseblab.com##img[name="js_ad"] sporcle.com##img[src^="data:image/png;base64,"] kino.to##img[src^="http://c.statcounter.com/"] + span inamsoftwares.com##img[src^="http://my.60ads.com/"] raysindex.com##img[style$="text-align: center; cursor: \a \a pointer; width: 728px;"] rejournal.com##img[style="border-width:0px;"] grabchicago.com##img[style="border: 0px solid ; width: 728px; height: 90px;"] thehackernews.com##img[style="border: 0px"] thebradentontimes.com##img[style="border:0px;width:120px;height:300px"] thebradentontimes.com##img[style="border:0px;width:180px;height:200px"] thebradentontimes.com##img[style="border:0px;width:180px;height:250px"] unblocked-piratebay.com##img[style="border:1px dotted black;"] noscript.net##img[style="float: left;padding: 32px 16px 8px 0; border: none"] world4free.in##img[style="height: 600px; width: 160px;"] knco.com##img[style="max-width:120px;max-height:480px;"] knco.com##img[style="max-width:180px;max-height:150px;"] linksave.in##img[style="max-width:468px; max-height:60px;"] knco.com##img[style="max-width:650px;max-height:90px;"] islamchannel.tv##img[style="vertical-align: top; width:468px; padding-left: 1px;padding-top: 5px;"] cnykiss.com##img[style="width: 160px; height: 160px;"] cbc-radio.com##img[style="width: 180px; float: left; height: 170px"] cbc-radio.com##img[style="width: 180px; float: right; height: 170px"] cnykiss.com,wutqfm.com##img[style="width: 180px; height: 180px;"] wutqfm.com##img[style="width: 200px; height: 200px;"] wcbm.com##img[style="width: 258px; height: 237px;"] wcbm.com##img[style="width: 261px; height: 256px;"] wbap.com##img[style="width: 299px; height: 85px;"] espncleveland.com##img[style="width: 300px; height: 100px; float: left;"] countryfile.com,wmal.com##img[style="width: 300px; height: 150px;"] dailymirror.lk,radiotoday.com.au##img[style="width: 300px; height: 200px;"] bulletin.us.com##img[style="width: 300px; height: 238px;"] dailymirror.lk##img[style="width: 300px; height: 248px;"] ktul.com##img[style="width: 300px; height: 24px; border: 0px;"] indypendent.org##img[style="width: 300px; height: 250px; "] flafnr.com,gizmochina.com##img[style="width: 300px; height: 250px;"] jq99.com##img[style="width: 300px; height: 75px;"] dailymirror.lk##img[style="width: 302px; height: 202px;"] ozarkssportszone.com##img[style="width: 320px; height: 160px;"] pricecheck.co.za##img[style="width: 460px;"] bulletin.us.com##img[style="width: 600px; height: 50px;"] indypendent.org##img[style="width: 728px; height: 90px;"] espn1420am.com##img[style="width: 900px; height: 150px;"] unionleader.com##img[style="width:100px;height:38px;margin-top:-10px"] globalincidentmap.com##img[style="width:120px; height:600px; border:0;"] thespiritsbusiness.com##img[style="width:170px;"] newsfirst.lk##img[style="width:300px; height:200px;"] klfm967.co.uk##img[style="width:468px;height:60px;border:0px;margin:0px;"] bitcoindifficulty.com##img[style="width:728px; height:90px;"] cryptoinfinity.com##img[style="width:728px;height:90px;"] tcweeklynews.com##img[title="AD: Advertising Graphics (11)"] ucreview.com##img[title="AD: Weekly Press (13)"] ucreview.com##img[title="AD: Weekly Press (14)"] ucreview.com##img[title="AD: Weekly Press (15)"] onhax.net##img[title="Download Now"] inmr.com##img[width="100"][height="18"] inmr.com##img[width="100"][height="36"] inmr.com##img[width="100"][height="38"] inmr.com##img[width="100"][height="44"] inmr.com##img[width="100"][height="50"] staradvertiser.com##img[width="101"][height="20"] abpclub.co.uk##img[width="118"] utahstories.com##img[width="120"][height="120"] scnsrc.net,traxarmstrong.com##img[width="120"][height="600"] americanisraelite.com,dailyblogtips.com,macintouch.com,utahstories.com,your-pagerank.com##img[width="125"][height="125"] samoaobserver.ws##img[width="130"][height="300"] reflector.com##img[width="130px"][height="52px"] thefinancialexpress-bd.com##img[width="145"] aerobaticsweb.org##img[width="150"][height="150"] zonalmarking.net##img[width="150"][height="750"] klfm967.co.uk##img[width="155"][height="167"] klfm967.co.uk##img[width="155"][height="192"] palipost.com##img[width="160"][height="100"] your-pagerank.com##img[width="160"][height="108"] radiocaroline.co.uk,yournews.com##img[width="160"][height="160"] zonalmarking.net##img[width="160"][height="300"] newswireni.com##img[width="160"][height="596"] airplaydirect.com,ata.org,candofinance.com,newswireni.com,serialbay.com,temulator.com,windfm.com##img[width="160"][height="600"] your-pagerank.com##img[width="160"][height="80"] your-pagerank.com##img[width="160"][height="89"] your-pagerank.com##img[width="160"][height="90"] newswireni.com##img[width="161"][height="600"] bilingualweekly.com##img[width="162"][height="170"] unionleader.com##img[width="165"][height="40"] sunny106.fm,tompkinsweekly.com,wutqfm.com##img[width="180"] wegoted.com,wyep.org##img[width="180"][height="150"] wegoted.com##img[width="180"][height="204"] wrno.com##img[width="185"][height="60"] favicon.co.uk##img[width="190"][height="380"] bayfm.co.za##img[width="195"][height="195"] rejournal.com##img[width="200"][height="100"] sarasotatalkradio.com##img[width="200"][height="200"] coffeegeek.com##img[width="200"][height="250"] professionalmuscle.com##img[width="201"] bayfm.co.za##img[width="208"][height="267"] bayfm.co.za##img[width="208"][height="301"] bayfm.co.za##img[width="208"][height="319"] professionalmuscle.com##img[width="210"] khow.com##img[width="216"][height="156"] thisdaylive.com##img[width="220"][height="147"] isportconnect.com##img[width="220"][height="150"] isportconnect.com##img[width="220"][height="200"] isportconnect.com##img[width="220"][height="300"] aroundhawaii.com##img[width="220"][height="60"] nufc.com##img[width="226"][height="58"] aroundhawaii.com##img[width="230"][height="150"] islamchannel.tv##img[width="230"][height="185"] mlfat4arab.com##img[width="234"][height="60"] mommymatters.co.za##img[width="249"][height="250"] phillyrecord.com##img[width="250"][height="218"] mommymatters.co.za##img[width="250"][height="250"] ukclimbing.com##img[width="250"][height="350"] yournews.com##img[width="250"][height="90"] tompkinsweekly.com##img[width="252"] theannouncer.co.za##img[width="252"][height="100"] tompkinsweekly.com##img[width="253"] ozarkssportszone.com##img[width="267"][height="294"] wrko.com##img[width="269"][height="150"] threatpost.com##img[width="270"] magicmiami.com##img[width="273"][height="620"] staugustine.com##img[width="275"][height="75"] worldfree4u.com##img[width="280"][height="250"] wwl.com##img[width="281"][height="141"] staugustine.com##img[width="285"][height="75"] nufc.com##img[width="287"][height="287"] nufc.com##img[width="288"][height="347"] mypbrand.com##img[width="295"] wareznova.com##img[width="298"][height="53"] inquirer.net##img[width="298"][style="margin-bottom:5px;margin-top:5px;"] africandesignmagazine.com,punchng.com,technomag.co.zw##img[width="300"] momsmiami.com,nehandaradio.com##img[width="300"][height="100"] fancystreems.com##img[width="300"][height="150"] 947wls.com##img[width="300"][height="155"] businessdayonline.com##img[width="300"][height="200"] redpepper.co.ug##img[width="300"][height="248"] 360nobs.com,airplaydirect.com,businessdayonline.com,ciibroadcasting.com,clutchmagonline.com,cryptomining-blog.com,dotsauce.com,fancystreems.com,movin100.com,mycolumbuspower.com,nehandaradio.com,redpepper.co.ug,rlslog.net,sacobserver.com,samoatimes.co.nz,seguintoday.com,staugustine.com,tangatawhenua.com,theannouncer.co.za,three.fm,wolf1051.com,ynaija.com,yomzansi.com##img[width="300"][height="250"] ynaija.com##img[width="300"][height="290"] linkbitty.com,newspapers-online.com##img[width="300"][height="300"] redpepper.co.ug##img[width="300"][height="360"] redpepper.co.ug##img[width="300"][height="420"] redpepper.co.ug##img[width="300"][height="500"] redpepper.co.ug##img[width="300"][height="528"] clutchmagonline.com##img[width="300"][height="600"] wallstreetsurvivor.com##img[width="310"][height="56"] wben.com##img[width="316"][height="120"] ciibroadcasting.com##img[width="325"][height="200"] radioasiafm.com##img[width="350"][height="300"] ipwatchdog.com##img[width="350px"][height="250px"] noordnuus.co.za##img[width="357"][height="96"] nufc.com##img[width="360"][height="100"] transportxtra.com##img[width="373"][height="200"] transportxtra.com##img[width="373"][height="250"] forum.blackhairmedia.com##img[width="400"][height="82"] gomlab.com##img[width="410"][height="80"] sunnewsonline.com##img[width="420"][height="55"] drum.co.za##img[width="422"][height="565"] powerbot.org##img[width="428"] inmr.com##img[width="450"][height="64"] webresourcesdepot.com##img[width="452px"][height="60px"] maltairport.com##img[width="453"][height="115"] ch131.so##img[width="460"][height="228"] 300mbmovies4u.com,chat-avenue.com,hollywoodbackwash.com,macintouch.com,muzique.com,wareznova.com##img[width="468"] abpclub.co.uk,allforpeace.org,cpaelites.com,forum.gsmhosting.com,hulkload.com,load.to,rlslog.net,thetobagonews.com,warezhaven.org,waz-warez.org##img[width="468"][height="60"] topprepperwebsites.com##img[width="468"][height="80"] infinitecourses.com##img[width="468px"][height="60px"] sharktankblog.com##img[width="485"][height="60"] yournews.com##img[width="540"][height="70"] sunny106.fm##img[width="560"][height="69"] sunny106.fm##img[width="570"][height="131"] staugustine.com##img[width="590"][height="200"] isportconnect.com##img[width="590"][height="67"] mail.macmillan.com,motortrader.com.my##img[width="600"] redpepper.co.ug##img[width="600"][height="117"] nufc.com##img[width="600"][height="85"] softpedia.com##img[width="600"][height="90"] bloombergtvafrica.com##img[width="628"][height="78"] radiotoday.co.uk##img[width="630"][height="120"] shanghaiist.com##img[width="640"][height="444"] motortrader.com.my##img[width="640"][height="80"] cryptothrift.com##img[width="700"] 1550wdlr.com##img[width="711"][height="98"] crackingforum.com##img[width="720"] businessdayonline.com,ch131.so##img[width="720"][height="90"] wharf.co.uk##img[width="720px"][height="90px"] lindaikeji.blogspot.com,livemixtapes.com,naija247news.com,powerbot.org,rsvlts.com,xtremesystems.org##img[width="728"] 9tools.org,add-anime.net,bodyboardingmovies.com,creditboards.com,dogepay.com,driverguide.com,ecostream.tv,freeforums.org,hulkload.com,imgbar.net,movin100.com,oldiesradio1050.com,radioinsight.com,sameip.org,tangatawhenua.com,thecsuite.co.uk,topprepperwebsites.com,wallstreetfool.com,warezlobby.org,wcfx.com,wolf1051.com,worldfree4u.com,wsoyam.com##img[width="728"][height="90"] mkfm.com##img[width="75"][height="75"] telecomtiger.com##img[width="768"][height="80"] americanisraelite.com##img[width="778"][height="114"] myretrotv.com##img[width="875"][height="110"] waz-warez.org##img[width="88"][height="31"] ptf.com##img[width="91"][height="13"] bilingualweekly.com##img[width="960"][height="70"] player.stv.tv##img[width="960px"][height="32px"] staugustine.com##img[width="970"][height="90"] lockerz.com##img[width="980"][height="60"] moneycontrol.com##img[width="996"][height="169"] vodu.ch##input[onclick^="parent.location='http://d2.zedo.com/"] vodu.ch##input[onclick^="parent.location='http://imads.integral-marketing.com/"] torrentcrazy.com##input[onclick^="window.open('http://adtransfer.net/"] onhax.net##input[type="button"][value^="Download"] bittorrent.am##input[value="Anonymous Download"] ad2links.com##input[value="Download Now"] wareznova.com##input[value="Download from DLP"] bittorrent.am##input[value="Download x10 faster"] lix.in##input[value="Download"] wareznova.com##input[value="Start Premium Downloader"] monova.org##input[value="Usenet"] politics.ie##ins[style="display:inline-table;border:none;height:250px;margin:0;padding:0;position:relative;visibility:visible;width:300px;background-color:transparent"] timesofisrael.com##item-spotlight yahoo.com##li[data-ad-enhanced="card"] yahoo.com##li[data-ad-enhanced="pencil"] yahoo.com##li[data-ad-enhanced="text"] webgurubb.com##li[data-author="Ads Master"] yahoo.com##li[data-beacon^="https://beap.adss.yahoo.com/"] yahoo.com##li[data-beacon^="https://beap.gemini.yahoo.com/"] yahoo.com##li[id^="ad-"] thefinancialbrand.com##li[id^="banner"] search.yahoo.com##li[id^="yui_"] > div[data-bns][data-bk][style="cursor: pointer;"] > div[class] twitter.com##li[label="promoted"] moneylife.in##li[style=" font-family:tahoma; font-size:11px; margin: 0px; border-bottom: 0px solid #ddd; padding: 5px 5px;"] ebayclassifieds.com##li[style="padding: 10px 0px; min-height: 90px;"] webmastertalkforums.com##li[style="width: 100%; height: 100px !important;"] cynagames.com##li[style="width: 25%; margin: 0; clear: none; padding: 0; float: left; display: block;"] psfk.com##li[style="width:300px; height:250px; margin-left: auto; margin-right:auto;"] bittorrent.am##noindex featve.com##object + script + div[class] stream4.tv##object[id^="stream"] + script + div[class] bitcoinfees.com##p > span[style="color:#aaaaaa; font-size:8pt;"] caclubindia.com##p[style="border: 1px black solid; width: 300px; height: 250px"] caclubindia.com##p[style="border:1px black solid;width:300px;height:100px"] ecommercetimes.com,linuxinsider.com,macnewsworld.com,technewsworld.com##p[style="clear: left;padding: 5px;border-top: solid 1px #cbcbcb;border-bottom: solid 1px #cbcbcb;"] c9tk.com##p[style="clear:both; padding:10px 5px 5px 5px; text-align:center;"] tweaktown.com##p[style="float:left;margin-right:10px"] diffen.com##p[style="float:right;width:340px;height:290px;padding:0;margin:0 0 0 15px;border:1px solid #DDD"] futureofcapitalism.com##p[style="font-size:11px; margin:0 0 2px 0; color:gray; text-align:center; letter-spacing:2px;"] lyricsmania.com##p[style="font-size:14px; text-align:center;"] history.ca##p[style="height:15px;"] midtownlunch.com##p[style="padding-bottom:295px"] truthdig.com##p[style="text-align: center; font-size: small;"] talkarcades.com##p[style="text-align: center; font-weight: bold; font-size: 150%;"] pcsx2.net##p[style="text-align: center;margin: 0px 160px -10px 0px;"] sorelatable.com##script + a[target="_blank"] service.mail.com##script + div[tabindex="1"] div[style="z-index:99996;position:absolute;cursor:default;background-color:white;opacity:0.95;left:0px;top:0px;width:1600px;height:552px;"] service.mail.com##script + div[tabindex="1"] div[style^="z-index:99998;position:absolute;cursor:default;left:0px;top:0px;width:"] koreaherald.com##section[style="border:0px;width:670px;height:200px;"] elitistjerks.com##small rokked.com##span[style="color: #555; font-size: 10px"] toucharcade.com##span[style="color:#555;"] bitsnoop.com##span[style="color:#AAA;font-size:9px;"] siteslike.com##span[style="display: block; height: 180px; margin-top: -1em;"] siteslike.com##span[style="display: block; height: 181px; margin-top: -1em;"] forum.ihubhost.net##span[style="font-family:arial,helvetica,sans-serif;"] washingtonmonthly.com##span[style="font-size:12px"] openwith.org##span[style="font-size:12px;"] iwannawatch.net##span[style="font-size:12px;margin-left:100px;"] lyricsmania.com##span[style="font-size:14px;"] liveleak.com##span[style="font-size:9px; font-weight:bold;"] techzilo.com##span[style="font-weight: 400; color: #888; font-size: 10px"] eurocardsharing.com,physicsforums.com##span[style="margin: 2px; float: left; width: 301px; height: 251px;"] windowsbbs.com##span[style="margin: 2px; float: left; width: 337px; height: 281px;"] thisoldhouse.com,whatismyip.com##span[style="margin: 2px; float: right; width: 301px; height: 251px;"] vidbux.com,vidxden.com##span[style="text-align:center; font-size: 10px"] forbes.com##span[style="text-transform:upercase;font-size:10px;color:999999;"] videobash.com##span[style="vertical-align: bottom; width: 300px; height: 241px;"] aninews.in##span[style="vertical-align: bottom; width: 302px; height: 270px;"] bitcointalk.org##span[style^="display:inline-block; width:700px"] sythe.org##table[align="center"][cellpadding="0"][style="width:1220px;"] forum.blackhairmedia.com##table[align="center"][style="padding-left:10px"] > tbody > tr > td[width="120"][valign="top"]:first-child forum.blackhairmedia.com##table[align="center"][style="padding-left:10px"] > tbody > tr > td[width="120"][valign="top"]:first-child + td[width="100%"][valign="top"] + td[width="120"][valign="top"]:last-child torrentportal.com##table[align="center"][width="800"] learninginfo.org##table[align="left"][width="346"] japantimes.co.jp##table[align="right"][width="250"] 411mania.com##table[align="right"][width="300"] officegamespot.com##table[bgcolor="#CCCCCC"] 4megaupload.com,ineedfile2.com##table[bgcolor="#D8D8D0"] geology.com##table[bgcolor="#cccccc"] webworldindex.com##table[bgcolor="#ceddf0"] search.vmn.net##table[bgcolor="#ecf5fa"] wwitv.com##table[bgcolor="222222"] biz.yahoo.com##table[bgcolor="white"][width="100%"] realitytvworld.com##table[border="0"][align="left"] mdpub.com##table[border="0"][align="top"][style="border: 1px red solid; "] omg-facts.com##table[border="0"][width="330px"][height="270px"] softexia.com##table[border="0"][width="728"][align="center"] shopping.net##table[border="1"][width="580"] majorgeeks.com##table[cellpadding="3"][align="center"] animecrave.com##table[cellpadding="3"][bgcolor="#F4F4F4"] digitimes.com##table[cellpadding="4"][bgcolor="#000000"] pcstats.com##table[cellpadding="5"][width="866"] talkgold.com##table[cellpadding="7"][align="center"] roadtester.com.au##table[cellpadding="9"][border="0"] chinapost.com.tw##table[cellspacing="0"][cellpadding="0"][border="0"][width="300"] iwebtool.com##table[cellspacing="0"][cellpadding="0"][border="1"] xtremedotnettalk.com##table[cellspacing="0"][cellpadding="5"][border="0"][width="100%"][style="background:#ffffff; margin:10px;padding:10px;"]:last-child chinapost.com.tw##table[cellspacing="1"][cellpadding="1"][bgcolor="#DD0000"][width="120"] rapidlibrary.com##table[cellspacing="1"][cellpadding="3"][border="0"][width="98%"] tdpri.com##table[cellspacing="2"][width="860"] dl4all.com##table[cellspacing="5"][background="#FFFFFF"] goal.com##table[cellspacing="5"][cellpadding="5"][style="float: right; width: 300px;"] ps3news.com##table[cellspacing="5px"] hotonlinenews.com,skyandtelescope.com##table[height="100"] daijiworld.com##table[height="100%"][cellspacing="0"][cellpadding="0"][border="0"][width="150"][style="border-left: 1px solid #000000"] playkidsgames.com##table[height="105"] airlinequality.com##table[height="110"][width="740"] empireonline.com##table[height="130"] dll-free-download.org##table[height="145"][width="789"] impulsegamer.com##table[height="200"][width="350"] foodnews.co.nz##table[height="217"] japantimes.co.jp##table[height="250"][width="250"] timesnewsline.com##table[height="250"][width="300"] theboxotruth.com##table[height="252"][bgcolor="#ffffff"][width="748"] wchstv.com##table[height="252"][width="320"] denimology.com##table[height="254"] tyrashow.warnerbros.com,wifinetnews.com##table[height="260"][width="310"] bitrebels.com##table[height="262"] airlinequality.com##table[height="270"][width="320"] i-tk.com##table[height="280"][width="180"] lyngsat-logo.com##table[height="320"] theboxotruth.com##table[height="33"][bgcolor="#ffffff"][width="760"] abundance-and-happiness.com##table[height="339"] officegamespot.com,ohgizmo.com,usconstitution.net##table[height="600"] softpanorama.org##table[height="620"] publichd.eu##table[height="75"][align="center"] curezone.com##table[height="80"][cellpadding="7"] car.com##table[height="90"][width="100%"] worldairportawards.com##table[height="90"][width="728"] indiaglitz.com##table[height="90"][width="740"] theboxotruth.com##table[height="90"][width="748"] billboard.biz##table[height="90px"][bgcolor="#CCCCCC"] worldairlineawards.com##table[height="95"][width="740"] legendarydevils.com##table[multilinks-noscroll="true"] thedailysheeple.com##table[style="background-color:#fdf1ca;"] jeepforum.com##table[style="border-width: 1px; border-color: gray; border-style: solid;"] monova.org##table[style="border: 1px solid #ccc; width: 85%; height: 250px;"] ngohq.com##table[style="border:1px solid #b2b2b2; width:153px; height:600px;"] dlsdownload.com##table[style="border:3px outset red;font-size:16px;background-color:#fdfcf0;margin-bottom:10px"] sina.com##table[style="margin-bottom:10px;border:0px solid #ddd;text-align:center;width:900px;height:100px;"] tower.com##table[style="margin-top:10px;"] rapid-search-engine.com##table[style="margin-top:5px;padding-top:10px;width:100%;background-color:#F5F8FE"] sharedir.com##table[style="margin:15px 0 0 -8px;width:540px"] bitsnoop.com##table[style="margin:6px 0 16px 0;padding:0px;"] i3investor.com##table[style="padding:8px;border:6px solid #dbdbdb;min-width:228px"] aniscartujo.com##table[style="position:absolute; left:0; top:0; z-index:999; border-collapse:collapse"] localstore.co.za##table[style="width: 952px; height: 90px; padding: 10px; border: 0; margin: 0 auto;"] playkidsgames.com##table[style="width:100%;height:105px;border-style:none;"] tower.com##table[style="width:160px; height:600px;padding:0px; margin:0px"] playkidsgames.com##table[style="width:320px;height:219px;border-style:none;background-color:#333333;margin:0 auto;"] tower.com##table[style="width:592px; height:200px;padding:0px; margin:0px"] tower.com##table[style="width:592px; height:65px;padding:0px; margin:0px"] website.informer.com##table[style="width:728px"] moneyearningforum.com##table[style="width:945px;text-align:center"] hotelnewsnow.com##table[style="width:970px;margin:0 auto;padding-bottom:10px;padding-top:10px;border-collapse:separate;border-spacing:0px;"] nufc.com##table[title="Ford Direct - Used Cars Backed by Ford"] chiff.com##table[title="Sponsored Links"] trucknetuk.com##table[width="100%"][bgcolor="#cecbce"] > tbody > tr > #sidebarright[valign="top"]:last-child linkreferral.com##table[width="100%"][height="1"] + table[width="750"][border="0"][bgcolor="ffffff"][cellspacing="0"][cellpadding="4"] wvtlfm.com##table[width="1024"][height="100"] atimes.com##table[width="120"] tvsite.co.za##table[width="120"][height="600"] thephuketnews.com##table[width="1215"][bgcolor="#DDDDDD"] aquariumfish.net##table[width="126"][height="600"] chinadaily.com.cn##table[width="130"][height="130"] sermonaudio.com##table[width="152"][bgcolor="C8D6C9"] afrol.com##table[width="159"][height="70"] curezone.com,ziddu.com##table[width="160"] theboxotruth.com##table[width="162"] audiforums.com##table[width="170"] curezone.com##table[width="180"] flipline.com##table[width="180"][height="100%"] articlebiz.com##table[width="200"][height="200"] news.excite.com##table[width="210"] excite.com,myway.com##table[width="210"][height="199"] articletrader.com,asiansexgazette.com,thestandard.com.hk##table[width="250"] font-cat.com##table[width="254"] foodnews.co.nz##table[width="270"] astrocenter.com,iloveuquotes.com,kanoodle.com,sextails.com,tennis.com,wwitv.com##table[width="300"] pcstats.com##table[width="300"][align="right"] highdefdigest.com##table[width="300"][cellspacing="0"][cellpadding="0"] business-standard.com,familyfun.go.com,idlebrain.com,itnewsonline.com,itweb.co.za,macsurfer.com,omgblog.com,themoviespoiler.com,ultimate-guitar.com##table[width="300"][height="250"] missoulian.com##table[width="300px"][height="487"] notdoppler.com##table[width="312"][height="252"] garfield.com##table[width="332"] idlebrain.com,lanewsmonitor.com,stickyminds.com,themoviespoiler.com##table[width="336"] iloveuquotes.com##table[width="350"] cameralabs.com##table[width="350"][align="right"][cellspacing="0"][cellpadding="0"][border="0"] flmsdown.net##table[width="435"][bgcolor="#575e57"] aquariumfish.net##table[width="440"][height="330"] fredericknewspost.com,geology.com,jeepforum.com,talkgold.com##table[width="468"] airlinequality.com##table[width="470"] worldtimezone.com##table[width="472"][border="0"][bgcolor="ffffff"] stampnews.com##table[width="482"][cellspacing="1"][cellpadding="0"] gardenstateapartments.com##table[width="486"] business-standard.com##table[width="490"][height="250"] abundance-and-happiness.com##table[width="500"] christiansunite.com##table[width="597"] lowellsun.com##table[width="599"] thegrumpiest.com##table[width="600"] animaltales.info##table[width="610"] imageporter.com,imgspice.com,pixroute.com##table[width="610"][height="260"] blingcheese.com##table[width="620"] rainbowdressup.com##table[width="620"][height="250"] scoop.co.nz##table[width="640"][height="254"] kingfiles.net##table[width="650px"] tvseriesfinale.com##table[width="658"] proaudioreview.com,rwonline.com,televisionbroadcast.com,tvtechnology.com,videography.com##table[width="665"] techlearning.com##table[width="665"][align="center"] 911tabs.com,airlinequality.com,animalcrossingcommunity.com,asiaone.com,craftster.org,dreamteammoney.com,forums.wirelessadvisor.com,jobsearch.monsterindia.com,jokes2go.com,linuxgizmos.com,talkgold.com##table[width="728"] monsterindia.com##table[width="728"][align="center"] softexia.com##table[width="728"][bordercolor="#003366"] serialbay.com##table[width="728"][cellspacing="0"][cellpadding="0"] oteupload.com##table[width="728"][height="430"] apanews.net,geekmontage.com,iphpbb3.com,silentera.com,webworldindex.com##table[width="728"][height="90"] knowfree.net##table[width="728px"][cellspacing="0"][cellpadding="0"][border="0"] monsterindia.com##table[width="730"][align="left"] font-cat.com##table[width="732"] airlinequality.com##table[width="736"] learnaboutmovieposters.com##table[width="744"][border="2"][bgcolor="#000000"][align="center"] gpdownloads.co.nz##table[width="760"][height="120"] sharedata.co.za##table[width="760"][height="60"] inquirer.net##table[width="780"][height="90"] asciiribbon.org,worldometers.info##table[width="800"] blackstarnews.com##table[width="800"][height="110"] blackstarnews.com##table[width="800"][height="130"] totallystressedout.com##table[width="800"][height="90"] g35driver.com##table[width="867"] curezone.com,curezone.org##table[width="88%"][height="10"] forums.syfy.com##table[width="900"][bgcolor="#3A3163"] aaroads.com##table[width="900"][height="110"] ksub590.com,newstalk890.com##table[width="910"][height="100"] asiaone.com##table[width="924"] newreviewsite.com##table[width="940"][height="60"] psl.co.za##table[width="952"][height="115"] psl.co.za##table[width="952"][height="64"] psl.co.za##table[width="952"][height="87"] japan-guide.com##table[width="965"][height="90"] scvnews.com##table[width="978"][height="76"] prowrestling.net##table[width="979"][height="105"] dining-out.co.za##table[width="980"][vspace="0"][hspace="0"] westportnow.com##table[width="981"] kool.fm##table[width="983"][height="100"] gamecopyworld.com##table[width="984"][height="90"] apanews.net##table[width="990"] cnykiss.com,wbkvam.com,wutqfm.com##table[width="990"][height="100"] cbc-radio.com##table[width="990"][height="100"][align="center"] 965ksom.com##table[width="990"][height="101"] wbrn.com##table[width="990"][height="98"] v8x.com.au##td[align="RIGHT"][width="50%"][valign="BOTTOM"] canmag.com##td[align="center"][height="278"] autosport.com##td[align="center"][valign="top"][height="266"][bgcolor="#dcdcdc"] coffeegeek.com##td[align="center"][width="100%"][valign="middle"] forums.battle.net##td[align="center"][width="130"] rapidog.com##td[align="left"][colspan="3"] thegrumpiest.com##td[align="left"][width="135px"] thegrumpiest.com##td[align="left"][width="135px"] + #table1 teenhut.net,whistlestopper.com##td[align="left"][width="160"][valign="top"] healthboards.com##td[align="left"][width="300"]:first-child notdoppler.com##td[background*="/img/topad_"] 959kissfm.com##td[background="/i/banner_back.jpg"] crackdb.cd##td[background="/img/tittel.gif"]:first-child > h1:first-child + h1:last-child vgcats.com##td[background="images/towerbanner.gif"] vgcats.com##td[background="images/widebanner.gif"] planetlotus.org##td[bgcolor="#BCCEDC"][align="center"][colspan="6"] planetlotus.org##td[bgcolor="#FFFFFF"][align="center"][colspan="6"] stickyminds.com##td[bgcolor="#acbcde"][width="100%"] appleinsider.com##td[bgcolor="#f5f5f5"] ixquick.com##td[bgcolor="#f7f9ff"] ixquick.com##td[bgcolor="#fbf0fa"] lyrics007.com##td[bgcolor="#ffcc00"][width="770"][height="110"] theboxotruth.com##td[bgcolor="#ffffff"][width="302"] puretna.com##td[class="colhead"][width="241"] titanshare.to,titantorrent.to##td[class^="downloadformat"] > a[onclick]:first-child:last-child express.co.uk##td[colspan="2"] schlockmercenary.com##td[colspan="3"] btmon.com##td[colspan="4"] ytmnd.com##td[colspan="5"] affiliatescout.com,freewarefiles.com,mysavings.com,techarp.com##td[height="100"] notdoppler.com##td[height="100"][rowspan="3"] everythinggirl.com,extremeoverclocking.com##td[height="104"] efytimes.com##td[height="108"] designboom.com,indianetzone.com##td[height="110"] lowyat.net,ultimatemetal.com##td[height="110px"] usautoparts.net##td[height="111"][align="center"][valign="top"] aspfree.com,devarticles.com,devshed.com##td[height="115"] bittorrent.am##td[height="120"][align="center"] officegamespot.com##td[height="120"][bgcolor="#FFFFFF"] 1980-games.com##td[height="129"][colspan="4"] ultimate-guitar.com##td[height="130"] eurometeo.com##td[height="14"][width="738"] eve-search.com##td[height="150"] autosport.com##td[height="17"] videohelp.com##td[height="200"] wrestlingnewsworld.com##td[height="204"] coolifiedgames.com,coolmath.com,elouai.com,spikesgamezone.com##td[height="250"] maxgames.com##td[height="250"][bgcolor="#fff"] vectorportal.com##td[height="250"][colspan="3"] honda-tech.com,tennis.com##td[height="250"][width="300"] dllme.com##td[height="260"] crictime.com##td[height="265"] autosport.com##td[height="266"][bgcolor="#DCDCDC"] kids-in-mind.com##td[height="270"][align="center"] rediff.com##td[height="280"] seriouswheels.com##td[height="289"] rediff.com,rentalads.com##td[height="290"] billionuploads.com##td[height="300"] lyngsat-logo.com##td[height="320"] cellular-news.com##td[height="350"] keepittrill.com##td[height="571"] moviesite.co.za##td[height="600"] musicjesus.com##td[height="600"][width="160"] talkgold.com##td[height="61"] tinyurl.com##td[height="610"][width="310"] crictime.com##td[height="641"] mybetting.co.uk##td[height="70"] businessknowhow.com##td[height="70"][colspan="3"] eve-search.com##td[height="90"] start64.com##td[height="92"][colspan="2"] crictime.com##td[height="93"] tigerdroppings.com##td[height="95"][bgcolor="#dedede"] imtranslator.net##td[height="96"] tinyurl.com##td[height="98"] searchalot.com##td[onmouseout="cs()"] bt-chat.com##td[rowspan="3"] ft.com##td[style=" width:125px; height:100px; vertical-align:top; "] tinyurl.com##td[style="background-color : #F1F0FF;"] themaineedge.com##td[style="background-color:#000000;"] thesonglyrics.com##td[style="background:url('http://www.thesonglyrics.com/pics/rcolbk.png'); border-left: 1px solid #003366; border-right: 1px solid #003366;"] hyipexplorer.com##td[style="border-bottom: 1px solid #EBEBEB; padding-right: 0px;"] newsfactor.com##td[style="border-left: #c0c0c0 solid 1px; padding-top:3px; padding-bottom:3px;"] dslreports.com##td[style="border-right: 1px #CCCCCC solid;"] nvnews.net##td[style="border: 0px solid #000000"][rowspan="3"] aquariumfish.net##td[style="border: 2px solid #FF0000; padding-top:8px; padding-bottom:8px"] 2flashgames.com##td[style="border:1px solid #a1b851;background:#ffffff;"] rapidog.com##td[style="font-size:11"] citationmachine.net##td[style="height: 100px;"] footytube.com##td[style="min-height: 292px; height: 250px; width: 342px; padding: 3px; padding-top:0px"] 360cities.net##td[style="min-width:210px;min-height:600px;"] cellular-news.com##td[style="padding-bottom:20px;"] jimbotalk.net##td[style="padding-bottom:3px; background-color:#ffffff; height:90px;"] kids-in-mind.com,kidsinmind.com##td[style="padding-left: 5; padding-right: 5"] imagebam.com##td[style="padding-right: 1px; text-align: left; font-size:15px;"] imagebam.com##td[style="padding-right: 2px; text-align: left; font-size:15px;"] newsfactor.com##td[style="padding-right: 5px; border-right: #BFBFBF solid 1px;"] mg.co.za##td[style="padding-top:5px; width: 200px"] bitcointalk.org##td[style="padding: 1px 1px 0 1px;"] > .bfl bitcointalk.org##td[style="padding: 1px 1px 0 1px;"] > .bvc bitcointalk.org##td[style="padding: 1px 1px 0 1px;"] > .gyft bitcointalk.org##td[style="padding: 1px 1px 0 1px;"] > a bitcointalk.org##td[style="padding: 1px 1px 0 1px;"] > b + span[style*="font-size: 18px;"] car.com##td[style="padding: 8px; border: 1px solid #C9D9DD; background-color: #F9F9FF;"] wikifeet.com##td[style="padding:10px"] business-standard.com##td[style="padding:5px"] healthsquare.com##td[style="padding:6px 0px 0px 4px;"] ultimate-guitar.com##td[style="padding:7px 0 10px 0; vertical-align:middle; text-align:center"] israbox.com##td[style="text-align: center; font-size: 16px; font-weight: bold;"] fresherscafe.com##td[style="text-align:center; height:120px; vertical-align:middle; border:#aaa 5px solid"] uploadc.com##td[style="text-align:center; vertical-align:middle; background:black"] tixati.com##td[style="vertical-align: top; text-align: right; width: 346px; font-size: 12px;"] englishforum.ch##td[style="width: 160px; padding-left: 15px;"] armslist.com##td[style="width: 190px; vertical-align: top;"] maannews.net##td[style="width: 250px; height: 120px; border: 1px solid #cccccc"] uvnc.com##td[style="width: 300px; height: 250px;"] mlbtraderumors.com##td[style="width: 300px;"] maannews.net##td[style="width: 640px; height: 80px; border: 1px solid #cccccc"] talkgold.com##td[style="width:150px"] riverdalepress.com##td[style="width:728px; height:90px; border:1px solid #000;"] billionuploads.com##td[valign="baseline"][colspan="3"] efytimes.com##td[valign="middle"][height="124"] efytimes.com##td[valign="middle"][height="300"] staticice.com.au##td[valign="middle"][height="80"] johnbridge.com##td[valign="top"] > .tborder[width="140"][cellspacing="1"][cellpadding="6"][border="0"] writing.com##td[valign="top"][align="center"][style="padding:10px;position:relative;"][colspan="2"] + .mainLineBorderLeft[width="170"][rowspan="4"]:last-child newhampshire.com##td[valign="top"][height="94"] cruisecritic.com##td[valign="top"][width="180"] cruisecritic.com##td[valign="top"][width="300"] cdcovers.cc##td[width="10"] linkreferral.com##td[width="100%"][bgcolor="dddddd"][align="right"] > table[width="800"][border="0"][align="center"][cellspacing="0"][cellpadding="0"] manoramaonline.com##td[width="1000"] gotquestions.org##td[width="1000"][height="93"] rawstory.com##td[width="101"][align="center"][style][margin="0"] worldtribune.com##td[width="1024"] evolutionm.net,forumserver.twoplustwo.com,itnewsonline.com,talkgold.com##td[width="120"] eq2flames.com##td[width="120"][style="padding-left:5px;white-space:normal"] forums.webrats.com##td[width="120px"]:first-child pojo.biz##td[width="125"] wetcanvas.com##td[width="125"][align="center"]:first-child zambiz.co.zm##td[width="130"][height="667"] manoramaonline.com##td[width="140"] songspk.link##td[width="145"][height="21"][style="background-color: #EAEF21"] leo.org##td[width="15%"][valign="top"][style="font-size:100%;padding-top:2px;"] appleinsider.com##td[width="150"] aerobaticsweb.org##td[width="156"][height="156"] zambiz.co.zm##td[width="158"][height="667"] gardenweb.com##td[width="159"][bgcolor="#A39614"] ap.org,billoreilly.com,complaints.com,pprune.org,thinkbabynames.com,ultimatemetal.com,worldometers.info##td[width="160"] eweek.com,terradaily.com##td[width="160"][align="left"] securityfocus.com##td[width="160"][bgcolor="#eaeaea"] manoramaonline.com##td[width="160"][height="600"] productreview.com.au,wirelessforums.org##td[width="160"][valign="top"] thegrumpiest.com##td[width="160px"] manoramaonline.com##td[width="165"] barbie.com##td[width="168"][height="640"] search.excite.co.uk##td[width="170"][valign="top"] tampermonkey.net##td[width="170px"][style="vertical-align: top; padding-top: 17px;"] everythinggirl.com##td[width="174"] moneymakerdiscussion.com##td[width="175"][style="padding-left: 15px"] appleinsider.com##td[width="180"] aaroads.com##td[width="180"][height="650"] themaineedge.com##td[width="180"][style="background-color:#335F9B; text-align: center;"] odili.net##td[width="180"][valign="top"] sys-con.com##td[width="180"][valign="top"][rowspan="3"] thaivisa.com##td[width="182"][valign="top"][style="padding-left:18px;"] couponmom.com##td[width="184"] eab.abime.net##td[width="185"][align="left"]:first-child gateprep.com##td[width="187"][style="padding:5px;"] muchshare.net##td[width="189"][align="left"] avsforum.com##td[width="193"] tivocommunity.com##td[width="193"][valign="top"] boxingscene.com##td[width="200"][height="18"] dir.yahoo.com##td[width="215"] thesonglyrics.com##td[width="230"][align="center"] itweb.co.za##td[width="232"][height="90"] degreeinfo.com,rubbernews.com##td[width="250"] bigresource.com##td[width="250"][valign="top"][align="left"] scriptmafia.org##td[width="250px"] stumblehere.com##td[width="270"][height="110"] websitelooker.com##td[width="30%"][align="center"] avsforum.com,ballerstatus.com,btobonline.com,coolmath-games.com,coolmath4kids.com,dzineblog.com##td[width="300"] softpedia.com##td[width="300"][align="right"] zigzag.co.za##td[width="300"][height="250"] musicsonglyrics.com,safemanuals.com,vector-logos.com##td[width="300"][valign="top"] ziddu.com##td[width="305"] bt-chat.com##td[width="305px"] pwtorch.com##td[width="306"][height="250"] tennis.com##td[width="330"][height="250"] devarticles.com,rage3d.com##td[width="336"] codewalkers.com##td[width="336"][valign="top"] net-security.org##td[width="337"][height="287"] planet-source-code.com##td[width="340"] rom-world.com##td[width="35%"][style="border: solid #AAAAAA 1px;"] askvg.com##td[width="370px"] storagereview.com##td[width="410"]:first-child + td[align="right"] freeonlinegames.com##td[width="50%"][height="250"] boxofficeindia.com##td[width="50%"][valign="top"][height="265"][align="left"] goodquotes.com##td[width="55%"] leo.org##td[width="55%"][valign="middle"] dickens-literature.com##td[width="7%"][valign="top"] ballerstatus.com,cellular-news.com,prowrestling.com,rivals.com##td[width="728"] itweb.co.za,lyngsat-logo.com,lyngsat.com,notdoppler.com,thinkbabynames.com##td[width="728"][height="90"] japan-guide.com##td[width="728"][valign="bottom"] postchronicle.com##td[width="728"][valign="top"] samachar.com##td[width="730"][height="90"] railmuseums.com##td[width="760"]:first-child + td[width="160"][valign="top"]:last-child barbie.com##td[width="767"][height="96"] gardenweb.com##td[width="932"][height="96"] the-numbers.com##td[width="95"] empireonline.com##td[width="950"][height="75"] workforce.com##td[width="970"][height="110"] usanetwork.com##td[width="970"][height="66"] howstuffworks.com##td[width="980"][height="90"] hongkongindians.com##th[width="1000"][height="141"] legendarydevils.com##th[width="600"] uvnc.com##tr > td[valign="middle"][style="width: 10px;"]:first-child + td[valign="top"][style="width: 180px;"] forums.creativecow.net##tr > td[width="126"][valign="top"][style="padding:6px 0px 0px 10px;"]:first-child rarlab.com,rarlabs.com##tr:first-child > .tbar2[width="48%"]:first-child + td[width="4%"] + .tbar2[width="48%"]:last-child topfriv.com##tr:first-child:last-child > td[style="padding-left:5px; width:260px"]:first-child rarlab.com,rarlabs.com##tr:last-child > td[valign="top"]:first-child + td + .tplain[valign="top"]:last-child fredericknewspost.com##tr[height="250"] whatsmyip.org##tr[height="95"] nowgoal.com##tr[id^="tr_ad"] fulldls.com##tr[style="height:40px;font-size:13px"] playkidsgames.com##tr[style="height:60px;"] internetslang.com##tr[style="min-height:28px;height:28px"] internetslang.com##tr[style="min-height:28px;height:28px;"] opensubtitles.org##tr[style^="height:115px;text-align:center;margin:0px;padding:0px;background-color:"] search.yahoo.com##ul > .res[data-bg-link^="http://r.search.yahoo.com/_ylt="] search.aol.com##ul[content="SLMP"] search.aol.com##ul[content="SLMS"] facebook.com##ul[id^="typeahead_list_"] > ._20e._6_k._55y_ elizium.nu##ul[style="padding: 0; width: 100%; margin: 0; list-style: none;"] ! Filter for testpages.adblockplus.org testpages.adblockplus.org###abptest ! *** easylist:easylist_adult/adult_specific_hide.txt *** ashemaletube.com###ASHM_imBox_Container nudography.com###BannerContainer porntack.com###BannerUnder cam4.com###Cam4IMslider starsex.pl###FLOW_frame thestranger.com###PersonalsScroller privatehomeclips.com###Ssnw2ik imagehaven.net###TransparentBlack namethatporn.com###a_block swfchan.com###aaaa pornvideoxo.com###abox 4tube.com###accBannerContainer03 4tube.com###accBannerContainer04 pornhub.com,tube8.com,youporn.com###access_container cliphunter.com,isanyoneup.com,seochat.com###ad imagefap.com###ad1 pornhub.com###adA pornhub.com###adB ua-teens.com###ad_global_below_navbar dagay.com###add_1 dagay.com###add_2 dachix.com,dagay.com###add_3 gaytube.com,pornomovies.com,turboimagehost.com,xvideos.com###ads eporner.com###adv hiddencamsvideo.com###advert primejailbait.com###advertical hairyclassic.com,qruq.com###advertisement pornative.com###advertisers timtube.com###advertising fleshbot.com###afleft fleshbot.com###afright xxxbunker.com###agePopup imageporter.com###agebox imagehaven.net###agreeCont imagevenue.com,intporn.com###ajax_load_indicator pornoitaliana.com,pornologo.com###alfa_promo_parent motherless.com###anonymous-notice literotica.com###b-top linkbucks.com###banner designm.ag###banner-holder dansmovies.com###banner4 xxxbunker.com###bannerListBottom xxxbunker.com###bannerListTop yuvutu.com###bannerTop debonairblog.com###banner_an adultfriendfinder.com###banner_con dansmovies.com###banner_video namethatpornstar.com###bannercontainer iafd.com###bantop desktopangels.net###bg_tab_container pornflex53.com###bigbox_adv xxxbunker.com###blackout chaturbate.com###botright porntube.com###bottomBanner xxxbunker.com###bottomBanners wankerhut.com###bottom_adv mydailytube.com###bottomadd watchindianporn.net###boxban2 pornsharia.com###brazzers1 fastpic.ru###brnd fastpic.ru###brnd-footer befuck.com,hotshame.com,pinkrod.com,pornoid.com,thenewporn.com,updatetube.com,wetplace.com###c2p xvideos.com###channel_banner 24porn7.com###closeSyntax_adpB drtuber.com###close_bottom_banner thestranger.com###communityScroller imagewaste.com###container2 trovaporno.com###corpo_video_sponsor thisav.com###dhtmlwindowholder blackandrose.net###disclaimer theync.com###divYNC-RC-BotAd theync.com###divYNC-RC-TopAd theync.com###divYNCFootAdHolder theync.com###divYNCFooterAdsWrapper theync.com###divYNCHeadAdHolder theync.com###divYNCVidPageAboveAdWrapper theync.com###divYNCVidPageBelowAdWrapper theync.com###divYNCVidPageBotAdWrapper theync.com###divYNCVidPageTopAdsWrapper celeb.gate.cc###div_alert celeb.gate.cc###div_alternative dojki.com###dosug xaxtube.com###download dominationtube.com###download-bar anyvids.com###eapromo efukt.com###ef-video-overlay adultdvdtalk.com###enter_overlay eporner.com###eptable crazyhomesex.com,deliciousmovies.com,homemademoviez.com,imgflare.com,momisnaked.com,momsteachboys.com,momsxboys.com,sex-movies.cc,topamateursexvideos.com###fadeinbox pornday.org,yporn.tv###featured imagetwist.com###firopage be3x.com###fl813695 sexyclips.org###flash loadsofpics.com###floatdiv monstertube.com###footer extremetube.com###footerWhole burningcamel.com###fp_promo adultfriendfinder.com###free_chat_models homemoviestube.com###friendscontents netasdesalim.com###frutuante cantoot.com###googlebox nangaspace.com###header freepornvs.com###header > h1 > .buttons aan.xxx###header-banner youtubelike.com###header-top cam4.com###headerBanner spankwire.com###headerContainer xaxtube.com###header_banner_1 xaxtube.com###header_banner_2 phonedog.com###headerboard dumpaporn.com###headerbottom todaysparent.com###hearst bonecasxxx.com###highlights prettyhotandsexy.sk###home-insert-1 fapdu.com###home_300_250 realgfporn.com###iknow gotgayporn.com###index4x4ad eporner.com###inpdiv eporner.com###inplayer imageporter.com###interVeil freebunker.com,imagesnake.com,imgcarry.com,loadsofpics.com,pornbus.org###introOverlayBg sex2ube.com###jFlowSlide perfectgirls.net,postyourpuss.com###leaderboard imagetwist.com###left[align="center"] > center > a[target="_blank"] collegegrad.com###leftquad suicidegirls.com###livetourbanner freeimgup.com,imghost.us.to###lj_livecams 5ilthy.com###ltas_overlay_unvalid ynot.com###lw-bannertop728 ynot.com###lw-top eporner.com###maindiv-topa eporner.com###maindiv-topadv news.com.au###match-widget xred2.com###mbEnd yobt.tv###media-bottom 5ilthy.com,cockcheese.com,filthyrx.com,gfssex.com###mediaspace adultfriendfinder.com###mod youporn.com,youporngay.com###moreVideosTabview3 askjolene.com###more_from_this protectlinks.com###mouselayer eporner.com###movieplayer-right starcelebs.com###mrskin-birthday-widget imagetwist.com###myad hollywoodrag.com###navcontainer alotporn.com,flashx.tv,myfreeblack.com###nuevoa ma3comic.com###omad newverhost.com###onload newverhost.com###onload-main newverhost.com###onload-overlay imagetwist.com,imagevenue.com,intporn.com###overlayBg heavy-r.com,vidiload.com###overlayVid videos.com###pToolbar jizzhut.com###pagetitle wide6.com###partner gamcore.com,wide6.com###partners extremetube.com,redtube.com,spankwire.com,youporngay.com###pb_block pornhub.com,tube8.com,youporn.com###pb_template youporn.com###personalizedHomePage > div:nth-child(2) pornhub.com###player + div + div[style] pornhub.com###player + div[style] vidgrab.net,xxvideo.us###player > #stop alotporn.com###playeradv depic.me###popup_div imagehaven.net###popwin sextvx.com###porntube_hor_bottom_ads sextvx.com###porntube_hor_top_ads xtube.com###postrollContainer kaktuz.com###postroller imagepost.com###potd eroclip.mobi,fuqer.com###premium youporn.com,youporngay.com###producer redtube.com###puBody drtuber.com,nuvid.com###puFloatDiv xvideoslatino.com###publicidadlateral1 xvideoslatino.com###publicidadlateral2 pussy.org###pussyhbanner pussy.org###pussytextlinks ma3comic.com###pxhead flurl.com###rectbanner yourlust.com###relatedBanner xxxymovies.com###reltabContent tnaflix.com###rightPromo homemoviestube.com###right_out nonktube.com###second amateurfarm.net,retrovidz.com###showimage shesocrazy.com###sideBarsMiddle shesocrazy.com###sideBarsTop pornday.org###side_subscribe_extra mydailytube.com###sideadd spankwire.com###sidebar imageporter.com###six_ban flurl.com###skybanner io9.com,postyourpuss.com###skyscraper imagedax.net,imagedunk.com,imageporter.com###slashpage free-celebrity-tube.com###slide_up2 fantasti.cc###smutty_widget porn.com###sp kindgirls.com###spon hiddencamshots.com,porn.com,sluttyred.com###sponsor dagay.com###sponsor_video_pub flingtube.com###sponsoredBy hiddencamshots.com###sponsors w3avenue.com###sponsorsbox maxjizztube.com,yteenporn.com###spotxt xxxbunker.com###ssLeft xxxbunker.com###ssRight gotgayporn.com,motherless.com###ss_bar hot-jav.com###stop privatehomeclips.com###stopImapwUx privatehomeclips.com###stopVAD eporner.com###subcontent_mediaspace cam4.com###subfoot adultfyi.com###table18 hostingfailov.com###tablespons xtube.com###tabs fleshasiadaily.com###text-12 fleshasiadaily.com###text-13 fleshasiadaily.com###text-14 fleshasiadaily.com###text-15 fleshasiadaily.com###text-8 fapgames.com###the720x90-spot filhadaputa.tv###thumb[width="959"] hiddencamshots.com,videarn.com###top-banner nude.hu###topPartners extremetube.com###topRightsquare xhamster.com###top_player_adv mataporno.com,sexmummy.com,sopervinhas.net,teenwantme.com,worldgatas.com,xpg.com.br###topbar pinkems.com###topfriendsbar namethatpornstar.com###topphotocontainer askjolene.com###tourpage pornhyve.com###towerbanner pornvideoxo.com###tube-right pervclips.com###tube_ad_category axatube.com,creampietubeporn.com,fullxxxtube.com,gallsin.xxx,xxxxsextube.com,yourdarkdesires.com###ubr usatoday.com###usat_PosterBlog homemoviestube.com###v_right stileproject.com###va1 stileproject.com###va2 stileproject.com###va3 stileproject.com###va4 stileproject.com###va5 stileproject.com###va6 stileproject.com###va7 stileproject.com###va8 teenist.com###video-bottom-right youporn.com###videoCanvas > .grid_5[style="height: 455px;"] spankwire.com###videoCounterStraight youporn.com###videoWrapper + div[style] bangyoulater.com###video_ad pornvideoscout.com,xsharebox.com###video_cover tube8.com###video_left_message adultfriendfinder.com###video_main_cams pornhyve.com###videobanners rextube.com###videoright pervclips.com,pornicom.com,wankoz.com###view_video_ad pornhub.com###views_left tjoob.com###viewvidright matureworld.ws###vote_popup adultfriendfinder.com###vp_left bustnow.com###xad900x250x1 mrstiff.com###xdv-preroll porntack.com##.Banner pornbanana.com##.DealContainer2 pornbanana.com##.RightBanners ziporn.com##.RightBoxMain ziporn.com##.RightRefBoxMain pornbanana.com##.TopBann porntack.com##.TopBannerCon pornbanana.com##.VidBottomBanner pornbanana.com##.VidRightSide extremetube.com##._mapm_link_local_sex extremetube.com##._mapm_link_phone_sex extremetube.com##._mapm_link_premium seductivetease.com##.a-center pornbb.org##.a1 porn.com##.aRight pornvideofile.com##.aWrapper celebspank.com,chaturbate.com,cliphunter.com,gamcore.com,playboy.com,pornhub.com,signbucks.com,sxx.com,tehvids.com,uflash.tv,wankoz.com,yobt.tv##.ad extremetube.com##.ad-container celebspank.com##.ad1 pornhub.com##.adContainer pornoxo.com##.adblock xxxfuel.com##.adcontainer sex3.com##.add-box hentaistream.com##.adds adultbox.eu,analtubegirls.com,bangyoulater.com,beemtube.com,cam4.com,djs-teens.net,femdom-fetish-tube.com,free-celebrity-tube.com,glarysoft.com,hdporn.in,onlyhot.biz,pornshaft.com,porntalk.com,ratemypeach.com,springbreaktubegirls.com,teentube18.com##.ads myfreeblack.com##.ads-player famouspornstarstube.com,hdporntube.xxx,lustypuppy.com,mrstiff.com,pixhub.eu,pornfreebies.com,tubedupe.com,webanddesigners.com,youngartmodels.net##.adv freexcafe.com##.adv1 privatehomeclips.com##.adv_block mygirlfriendvids.net,wastedamateurs.com##.advblock porn.hu##.advert fakku.net,pornmd.com,porntube.com,youporn.com,youporngay.com##.advertisement alphaporno.com,bravotube.net,privatehomeclips.com,tubewolf.com##.advertising fapdu.com##.aff300 askjolene.com##.aj_lbanner_container ah-me.com,befuck.com,pornoid.com,sunporno.com,thenewporn.com,twilightsex.com,updatetube.com,videoshome.com,xxxvogue.net##.allIM pinkrod.com,pornsharia.com,pornsharing.com,wetplace.com##.allIMwindow 1loop.com##.asblock literotica.com##.b-s-share-love fuqer.com##.b300x250 nude.hu##.badHeadline devatube.com##.ban-list gayboystube.com##.bancentr fux.com##.baner-column xchimp.com##.bannadd chaturbate.com,dansmovies.com,fecaltube.com,imageporter.com,playvid.com,private.com,vid2c.com,videarn.com,vidxnet.com,wanknews.com,watchhentaivideo.com,xbabe.com,yourdailygirls.com##.banner watchindianporn.net##.banner-1 adultpornvideox.com##.banner-box tube8.com##.banner-container 0xxx.in##.banner-naslovna watchindianporn.net##.banner-vid definebabe.com##.banner1 celebritymovieblog.com##.banner700 watchhentaivideo.com##.bannerBottom 4tube.com,empflix.com,tnaflix.com##.bannerContainer 4tube.com##.banner_btn wunbuck.com##.banner_cell galleries-pornstar.com##.banner_list penthouse.com##.banner_livechat freeporn.com##.bannercube xfanz.com##.bannerframe thehun.net##.bannerhorizontal bustnow.com##.bannerlink chubby-ocean.com,cumlouder.com,grandpaporntube.net,sexu.com,skankhunter.com##.banners isanyoneup.com##.banners-125 porntubevidz.com##.banners-area vid2c.com##.banners-aside 5ilthy.com##.bannerside sexoncube.com##.bannerspot-index thehun.net##.bannervertical ratemymelons.com##.bannus redtube.com##.belowVideo tnaflix.com##.bgDecor eskimotube.com,tjoob.com##.bg_banner_l eskimotube.com,tjoob.com##.bg_banner_r bangyoulater.com##.big-box-border tub99.com##.bigimg2 drtuber.com##.bl[style="height: auto;"] twilightsex.com##.bl_b_l japan-whores.com##.block-banners mylifetime.com##.block-doubleclick youx.xxx##.block-sites xhamster.com##.block[style="text-align:center; width:902px; padding:15px;margin:0"] streamsexclips.com,tubesexclips.com,tubesexmovies.com##.botban fux.com##.bottom-baner xbabe.com,yumymilf.com##.bottom-banner playvid.com##.bottom-banners youtubelike.com##.bottom-thumbs youtubelike.com##.bottom-top pornvideoxo.com##.bottom_wide tube8.com##.bottomadblock tube8.com##.box-thumbnail-friends worldsex.com##.brandreach sublimedirectory.com##.browseAd xaxtube.com##.bthums realgfporn.com##.btn-info 4tube.com,tube8.com##.btnDownload redtube.com##.bvq redtube.com##.bvq-caption gamesofdesire.com##.c_align empflix.com##.camsBox tnaflix.com##.camsBox2 celebspank.com##.celeb_bikini adultfriendfinder.com##.chatDiv.rcc voyeur.net##.cockholder xnxx.com##.combo.smallMargin[style="padding: 0px; width: 100%; text-align: center; height: 244px;"] xnxx.com##.combo[style="padding: 0px; width: 830px; height: 244px;"] avn.com##.content-right[style="padding-top: 0px; padding-bottom: 0px; height: auto;"] xbutter.com##.counters pervclips.com,pornicom.com##.cs dronporn.com##.cs_spon alotporn.com##.cube pornalized.com,pornoid.com,pornsharia.com##.discount pornsharia.com##.discounts fapdu.com##.disp-underplayer keezmovies.com##.double_right cameltoe.com##.downl pinkrod.com,pornsharia.com,wetplace.com##.download realgfporn.com##.downloadbtn hellporno.com##.dvb-advertisements pornsharia.com##.eciframe pornsharia.com##.eciframeright efukt.com##.ef_block_wrapper goldporntube.com##.embadv grandpaporntube.net##.embed_banners grandpaporntube.net##.exo imagepost.com##.favsites mrstiff.com##.feedadv-wrap extremetube.com##.float-left[style="width: 49.9%; height: 534px;"] wankerhut.com##.float-right extremetube.com##.float-right[style="width: 49.9%; height: 534px;"] teensexyvirgins.com,xtravids.com##.foot_squares scio.us##.footer babesandstars.com##.footer_banners cam111.com##.g_p_con300250 sammobile.com##.gad youx.xxx##.gallery-link youtubelike.com##.gallery-thumbs pornhub.com##.gay-ad-container titsintops.com##.gensmall[width="250"] titsintops.com##.gensmall[width="305"] fantasti.cc##.goodie01 ziporn.com##.hBannerHolder bgafd.co.uk##.hdradclip pornsharia.com##.head > h3 celebspank.com##.header redtube.com##.header > #as_1 nuvid.com##.holder_banner pornhub.com##.home-ad-container + div alphaporno.com##.home-banner tube8.com##.home-message + .title-bar + .cont-col-02 julesjordanvideo.com##.horiz_banner orgasm.com##.horizontal-banner-module orgasm.com##.horizontal-banner-module-small pornanal.net##.i_br drtuber.com##.img_video pornsis.com##.indexadl pornsis.com##.indexadr pornicom.com##.info_row2 cocoimage.com,hotlinkimage.com,picfoco.com##.inner_right e-hentai.org##.itd[colspan="4"] namethatporn.com##.item_a sex2ube.com##.jFlowControl teensanalfactor.com##.job pornhub.com##.join redtube.com##.join-button extremetube.com##.join_box pornhub.com,spankwire.com,tube8.com,youporn.com##.join_link overthumbs.com##.joinnow zuzandra.com##.jx-bar tnaflix.com##.leftAbsoluteAdd xxxporntalk.com##.left_col taxidrivermovie.com##.left_right_border xxxporntalk.com##.leftsidenav galleries-pornstar.com##.list_sites sexyfunpics.com##.listingadblock300 tnaflix.com##.liveJasminHotModels ns4w.org##.livejasmine madthumbs.com##.logo tube8.com##.main-video-wrapper > .float-right sexdepartementet.com##.marketingcell lic.me##.miniplayer hanksgalleries.com##.mob_vids redtube.com##.ntva finaid.org##.one lustgalore.com,yourasiansex.com##.opac_bg baja-opcionez.com##.opaco2 vporn.com##.overheaderbanner drtuber.com##.p_adv tube8.com##.partner-link bravotube.net##.paysite ah-me.com##.paysite-link madmovs.com,pornosexxxtits.com##.player-outer-banner 4tube.com##.player_faq_link 4tube.com##.player_sub_link yobt.tv##.playpause.visible > div hornywhores.net##.post + script + div[style="border-top: black 1px dashed"] hornywhores.net##.post + script + div[style="border-top: black 1px dashed"] + br + center uflash.tv##.pps-banner pornhub.com##.pre-footer porntubevidz.com##.promo-block nakedtube.com,pornmaki.com##.promotionbox nuvid.com##.puFloatLine sexy-toons.org##.pub300 cumlouder.com,freemovies.tv##.publis-bottom pussy.org##.pussytrbox xchimp.com##.rCol2 bustedcoverage.com##.rcr-tower candidvoyeurism.com##.rectangle burningcamel.com##.reklaim cam4.com##.removeAds tubaholic.com##.result_under_video youporn.com##.right-column > div[style^="float: none;"]:first-child youporn.com##.right-column aside[class^="pad-right"] porn.com##.right300 tnaflix.com##.rightAbsoluteAdd xxxporntalk.com##.rightalt-1 > center > a[target="_blank"] > img[width="160"] porn.com##.rmedia collegegrad.com##.roundedcornr_box_quad xxxymovies.com##.rtoptbl sticking.com##.sb-box dominationtube.com,gaysexarchive.com,skeezy.com,sticking.com##.sb-txt uselessjunk.com##.shadow_NFL sankakucomplex.com##.side300xmlc celebspank.com##.sidebar5 4tube.com##.sidebarVideos vidxnet.com##.sidebar_banner cliphunter.com##.sidecreative xxxporntalk.com##.sidenav 4tube.com##.siteBannerHoriz tube8.com##.skin tube8.com##.skin1 tube8.com##.skin2 tube8.com##.skin3 tube8.com##.skin4 tube8.com##.skin6 tube8.com##.skin7 candidvoyeurism.com##.skyscraper gaytube.com##.slider-section movies.askjolene.com##.small_tourlink springbreaktubegirls.com##.span-100 nonktube.com##.span-300 nonktube.com##.span-320 ns4w.org##.splink bgafd.co.uk##.spnsr abc-celebs.com##.spons definebabe.com,pornever.net,xbabe.com##.sponsor definebabe.com##.sponsor-bot xhamster.com##.sponsorB xxxbunker.com##.sponsorBoxAB xhamster.com##.sponsorS xhamster.com##.sponsor_top proporn.com,tubecup.com,xhamster.com##.spot magicaltube.com##.spot-block tubecup.com##.spot_bottom redtube.com##.square-banner sunporno.com,twilightsex.com##.squarespot babesandstars.com##.srcreen sexyandshocking.com##.sub-holder peepinghunter.com##.superbanner porndaddy.us##.svd dickbig.net##.t_14 intporn.com##.tagcloudlink.level4 amateuralbum.net##.tb3 hungangels.com##.tborder[width="160"][cellspacing="0"][cellpadding="4"][border="0"] amateurvoyeurforum.com##.tborder[width="99%"][cellpadding="6"] imagepost.com##.textads1 extremetube.com##.title-sponsor-box galleries-pornstar.com##.title_slider popporn.com,xxxlinks.es##.top-banner sunporno.com##.top-player-link 10movs.com##.top_banner pornhub.com##.top_hd_banner mrstiff.com##.topad peepinghunter.com##.topbanner itsatechworld.com##.topd realgfporn.com##.trade-slider overthumbs.com##.trailerspots tubedupe.com##.treview_link_1 tubedupe.com##.tube_review avn.com##.twobannersbot avn.com##.twobannersbot-bot dumparump.com##.txt8pt[width="120"] sunporno.com##.under-player-link bravotube.net##.under-video indianpornvideos.com##.vdo-unit julesjordanvideo.com##.vertical_banner freepornvs.com##.vib > .cs h2porn.com##.video-banner hdporntube.xxx##.video-link redtube.com##.video-page japan-whores.com##.video-provider alphaporno.com,tubewolf.com##.video-sponsor tube8.com##.videoPageSkin tube8.com##.videoPageSkin1 tube8.com##.videoPageSkin2 4tube.com##.videoSponsor h2porn.com##.video_banner bonertube.com##.videoad940 indianpornvideos.com##.videoads sexyshare.net##.videosz_banner youporn.com##.views_left lubetube.com##.viewvideobanner imagearn.com##.wide_banner beeg.com##.window mrskin.com##.yui3-u-1-3:last-child porn.com##.zone xhamster.com##[height="280"][width="960"] imagehaven.net##[href="http://clicks.totemcash.com/?s=38739&p=21&pp=4"] imagevenue.com##[id^="MarketGid"] liveleak.com##[style="color: rgb(204, 0, 0);"] subimg.net##[style="float: left; padding-left: 43px; padding-top: 21px;"] hollywoodrag.com,imagefap.com##[style="font-weight: bold; font-family: Arial; font-size: 13px;"] homemade-voyeur.com##[style="height:250px;"] starpix.us##[style="left: 644px; top: 552.5px; visibility: visible;"] pornerbros.com##[style="margin: -150px auto 0px; width: 920px; height: 400px;"] myprops.org##[style="padding-top: 15px; padding-left: 81px;"] sexyclips.org##[style="text-align: center; width: 1000px; height: 250px;"] yuvutu.com##[width="480px"][style="padding-left: 10px;"] exgirlfriendmarket.com##[width="728"][height="150"] 264porn.blogspot.com##[width="728"][height="90"] matureworld.ws##a > img[height="180"][width="250"][src*=".imageban.ru/out/"] asspoint.com,babepedia.com,babesource.com,gaytube.com,girlsnaked.net,pornoxo.com,rogreviews.com,starcelebs.com,the-new-lagoon.com,tube8.com##a[href*=".com/track/"] tube8.com##a[href*="/affiliates/idevaffiliate.php?"] monstercockz.com##a[href*="/go/"] tube8.com##a[href*="?coupon="] porn99.net##a[href="http://porn99.net/asian/"] xhamster.com##a[href="http://premium.xhamster.com/join.html?from=no_ads"] pornwikileaks.com##a[href="http://www.adultdvd.com/?a=pwl"] footfetishtube.com##a[href="http://www.footfetishtube.com/advertising_banner.php"] twinsporn.net##a[href="http://www.herbostore.net/mens-health/spermomax.html"] stockingstv.com##a[href="http://www.stockingstv.com/banners/default.php"] hornywhores.net##a[href="https://cosyupload.com/affiliate"] imagevenue.com##a[href^=" http://www.pinporn.com"] fecaltube.com##a[href^="/go/"] anyvids.com##a[href^="http://ad.onyx7.com/"] sex4fun.in##a[href^="http://adiquity.info/"] tube8.com##a[href^="http://ads.trafficjunky.net"] tube8.com##a[href^="http://ads2.contentabc.com"] pornbb.org##a[href^="http://ard.ihookup.com/"] pornbb.org##a[href^="http://ard.sexplaycam.com/"] porn99.net##a[href^="http://bit.ly/"] sex4fun.in##a[href^="http://c.mobpartner.mobi/"] sex3dtoons.com##a[href^="http://click.bdsmartwork.com/"] xxxgames.biz##a[href^="http://clicks.totemcash.com/?"] imghit.com##a[href^="http://crtracklink.com/"] celeb.gate.cc##a[href^="http://enter."][href*="/track/"] hollywoodoops.com##a[href^="http://exclusive.bannedcelebs.com/"] gamcore.com##a[href^="http://gamcore.com/ads/"] hentai-imperia.org,rs-linkz.info##a[href^="http://goo.gl/"] celeb.gate.cc##a[href^="http://join."][href*="/track/"] porn99.net##a[href^="http://lauxanh.us/"] incesttoons.info##a[href^="http://links.verotel.com/"] xxxfile.net##a[href^="http://netload.in/index.php?refer_id="] imagepix.org##a[href^="http://putana.cz/index.php?partner="] iseekgirls.com,small-breasted-teens.com,the-new-lagoon.com,tube8.com##a[href^="http://refer.ccbill.com/cgi-bin/clicks.cgi?"] olala-porn.com##a[href^="http://ryushare.com/affiliate."] hentairules.net##a[href^="http://secure.bondanime.com/track/"] hentairules.net##a[href^="http://secure.futafan.com/track/"] hentairules.net##a[href^="http://secure.lestai.com/track/"] filthyrx.com##a[href^="http://secure.spitsters.com/track/"] hentairules.net##a[href^="http://secure.titanime.com/track/"] youngpornvideos.com##a[href^="http://teensexmania.com/jump.php?"] asianpornmovies.com##a[href^="http://tour.teenpornopass.com/track/"] asianpornmovies.com##a[href^="http://webmasters.asiamoviepass.com/track/"] imagetwist.com##a[href^="http://www.2girlsteachsex.com/"] nifty.org##a[href^="http://www.adlbooks.com/"] hentai-imperia.org##a[href^="http://www.adult-empire.com/rs.php?"] picfoco.com##a[href^="http://www.adultfriendfinder.com/search/"] bravotube.net##a[href^="http://www.bravotube.net/cs/"] free-adult-anime.com##a[href^="http://www.cardsgate-cs.com/redir?"] celeb.gate.cc##a[href^="http://www.cashdorado.de/track/"] freeones.com##a[href^="http://www.clickthruserver.com/cgi-bin/banner/"] filthdump.com##a[href^="http://www.filthdump.com/adtracker.php?"] alotporn.com##a[href^="http://www.fling.com/"] myfreeblack.com##a[href^="http://www.fling.com/enter.php"] freeporninhd.com##a[href^="http://www.freeporninhd.com/download.php?"] xhamster.com##a[href^="http://www.linkfame.com/"] girlsnaked.net##a[href^="http://www.mrvids.com/out/"] sluttyred.com##a[href^="http://www.realitykings.com/main.htm?id="] redtube.com##a[href^="http://www.redtube.com/click.php?id="] motherless.com##a[href^="http://www.safelinktrk.com/"] sex3dtoons.com##a[href^="http://www.shinydollars.com/sites/3dld/?id="] xxxprivates.com##a[href^="http://www.xxxprivates.com/out-sponsor-"] prestashop.com##a[href^="https://partners.a2hosting.com/solutions.php?id="] freeporninhd.com##a[onclick^="window.open('http://www.freeporninhd.com/cb5.php"] literotica.com##a[style="display: block; text-align: center; font-family: Arial, Helvetica, sans-serif; font-size: 110%;"] avn.com##a[style="position: absolute; top: -16px; width: 238px; left: -226px; height: 1088px;"] avn.com##a[style="position: absolute; top: -16px; width: 238px; right: -226px; height: 1088px;"] oopspicture.com##a[target="_blank"] > img[alt="real amateur porn"] imagevenue.com##a[target="_blank"][href*="&utm_campaign="] imagevenue.com##a[target="_blank"][href*="http://trw12.com/"] youporn.com##a[target="_blank"][href^="http://www.youporn.com/"] > img[src^="http://www.youporn.com/"] picfoco.com##a[title="Sponsor link"] showyourdick.org##center + hr + table[width="800"][align="center"] sex3dtoons.com##div[align="center"] > table[width="940"][cellspacing="0"][cellpadding="0"][border="0"] jailbaitgallery.com##div[align="center"][style="margin-bottom: 15px;"] babesandbitches.net##div[class^="banner"] tube8.com##div[class^="footer-ad"] pornhub.com##div[id$="rightColVideoPage"] > div[style]:first-child celeb.gate.cc##div[id^="bnrrotator_"] pornuppz.info##div[id^="dyn"][style^="position: fixed; left: 30px; top: 20px; z-index:"] hentaistream.com##div[id^="hs_ad"] eporner.com##div[style$=" border:1px solid #666666;"] casanovax.com##div[style="background-color: #5B1111; width: 728px; height: 90px; text-align: center; margin: auto;"] xtravids.com##div[style="background-color:#DDD; padding:5px;"] x3xtube.com##div[style="border: 1px solid red; margin-bottom: 15px;"] crazyandhot.com##div[style="border:1px solid #000000; width:300px; height:250px;"] imagecherry.com##div[style="border:1px solid black; padding:15px; width:550px;"] voyeur.net##div[style="display:inline-block;vertical-align:middle;margin: 2px;"] redtube.com##div[style="float: none; height: 250px; position: static; clear: both; text-align: left; margin: 0px auto;"] pornhub.com##div[style="float: none; width: 950px; position: static; clear: none; text-align: center; margin: 0px auto;"] redtube.com##div[style="float: right; height: 330px; width: 475px; position: relative; clear: left; text-align: center; margin: 0px auto;"] redtube.com##div[style="float: right; height: 528px; width: 300px; position: relative; clear: left; text-align: center; margin: 0px auto;"] xhamster.com##div[style="font-size: 10px; margin-top: 5px;"] redtube.com##div[style="height: 250px; position: static; clear: both; float: none; text-align: left; margin: 0px auto;"] redtube.com##div[style="height: 250px; position: static; float: none; clear: both; text-align: left; margin: 0px auto;"] redtube.com##div[style="height: 250px; position: static; float: none; clear: both; text-align: left;"] pichunter.com##div[style="height: 250px; width: 800px; overflow: hidden;"] xxxstash.com##div[style="height: 250px; width: 960px;"] redtube.com##div[style="height: 330px; width: 475px; position: relative; float: right; clear: left; text-align: center; margin: 0px auto;"] empflix.com##div[style="height: 400px;"] redtube.com##div[style="height: 528px; width: 300px; position: relative; float: right; clear: left; text-align: center;"] querverweis.net##div[style="height:140px;padding-top:15px;"] fantasti.cc##div[style="height:300px; width:310px;float:right; line-height:10px;margin-bottom:0px;text-align:center;"] pornmade.com##div[style="margin-left:40px;width:600px; background-color:#FBF8F1;padding:20px;margin-top:20px;border-top:1px solid #909090;border-left:1px solid #909090;border-right:1px solid #909090;border-bottom:1px solid #909090;-webkit-border-top-right-radius:10px;-webkit-border-top-left-radius:10px;-webkit-border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px;"] data18.com##div[style="margin-top: 6px; margin-left: 6px; width: 293px; height: 200px; overflow: hidden;"] pornmade.com##div[style="margin-top:100px;border:1px solid black;padding:10px;background:#fff;z-index:999;overflow:hidden;width:255px;"] pornerbros.com##div[style="margin: 10px auto; text-align: center;"] pornmade.com##div[style="margin:0 auto;padding:10px;border:2px solid black;background-color:white;width:960px;"] eccie.net##div[style="overflow: hidden; width: 728px; height: 90px"] freeones.com##div[style="padding: 0px; margin: 10px 0px; height: 100px; width: 898px; background-color: #4C89F9; border: 1px solid #4C89F9"] definebabe.com##div[style="padding:5px 15px 5px 15px;height:228px;background-color:#000000;"] pornhub.com##div[style="position: static; float: none; clear: none; text-align: center; margin: 0px auto;"] pornhub.com##div[style="position: static; float: none; clear: none; text-align: center;"] pornhub.com##div[style="position: static; height: 75px; float: none; clear: none; text-align: center; margin: 0px auto;"] twinsporn.net##div[style="position:fixed;right:10px;bottom:10px;color:#ff0000;border:0;"] videarn.com##div[style="text-align: center; margin-bottom: 10px;"] xtube.com##div[style="text-align:center; width:1000px; height: 150px;"] sluttyred.com##div[style="width: 300px; height: 250px; background-color: #CCCCCC;"] givemegay.com##div[style="width: 300px; height: 250px; margin: 0 auto;margin-bottom: 10px;"] vid2c.com##div[style="width: 300px; height: 280px; margin-left: 215px; margin-top: 90px; position: absolute; z-index: 999999998; overflow: hidden; border-radius: 10px; transform: scale(1.33); background-color: black; opacity: 0.8; display: block;"] pornhub.com##div[style="width: 380px; margin: 0 auto;background-color: #101010;text-align: center;"] vporn.com##div[style="width: 720px; height: 90px; text-align: center; overflow: hidden;"] casanovax.com##div[style="width: 728px; height: 90px; text-align: center; margin: auto"] crazyandhot.com##div[style="width: 728px; height: 90px; text-align: left;"] pichunter.com##div[style="width: 800px; height: 250px; overflow: hidden;"] pornhub.com##div[style="width: 950px; float: none; position: static; clear: none; text-align: center; margin: 0px auto;"] pornhub.com##div[style="width: 950px; position: static; clear: none; float: none; text-align: center; margin: 0px auto;"] pornhub.com##div[style="width: 950px; position: static; float: none; clear: none; text-align: center; margin: 0px auto;"] xogogo.com##div[style="width:1000px"] iloveinterracial.com##div[style="width:1000px;height:110px; background-color:#E9DECA; font-family: Tahoma,Helvetica,Arial,sans-serif; font-size: 11px; font-style:normal; color:#535353;"] sexbot.com##div[style="width:300px;height:20px;text-align:center;padding-top:30px;"] imgbabes.com##div[style="width:604px; height:250px; background:#241521; padding:4px 3px 4px 3px; margin-top:-5px; margin-bottom:-8px; -moz-border-radius:2px; border-radius:2px; -webkit-border-radius:2px;"] cam111.com##div[style="width:626px; height:60px; margin-top:10px; margin-bottom:10px;"] cam111.com##div[style="width:627px; height:30px; margin-bottom:10px;"] efukt.com##div[style="width:630px; height:255px;"] newbigtube.com##div[style="width:640px; min-height:54px; margin-top:8px; padding:5px;"] briefmobile.com##div[style="width:728px;height:90px;margin-left:auto;margin-right:auto;margin-bottom:20px;"] tmz.com##div[style^="display: block; height: 35px;"] shockingtube.com##div[style^="display: block; padding: 5px; width:"] eporner.com##div[style^="height:250px; width:1198px;"] eporner.com##div[style^="height:250px; width:300px;"] pornvideoxo.com##div[style^="width: 470px; height: 64px;"] eporner.com##div[style^="width:1198px; height:250px;"] eporner.com##div[style^="width:300px; height:250px;"] imgflare.com##div[style^="width:604px; height:250px;"] rateherpussy.com##font[size="1"][face="Verdana"] nude.hu##font[stlye="font: normal 10pt Arial; text-decoration: none; color: black;"] cliphunter.com##h2[style="color: blue;"] pornhub.com,redtube.com##iframe luvmilfs.com##iframe + div > div[style="position: absolute; top: -380px; left: 200px; "] youporn.com##iframe[frameborder] javjunkies.com##iframe[height="670"] youporn.com##iframe[style="height: 250px; width: 300px; position: static; float: none; clear: none; text-align: start;"] youporn.com##iframe[style="height: 250px; width: 950px; float: none; position: static; clear: both; text-align: center; margin: 0px auto;"] youporn.com##iframe[style="height: 250px; width: 950px; position: static; float: none; clear: both; text-align: center;"] youporn.com##iframe[width="300"][height="250"] yourasiansex.com##iframe[width="660"] imagevenue.com##iframe[width="728"][height="90"] videosgls.com.br##iframe[width="800"] xxxgames.biz##img[height="250"][width="300"] pornhub.com##img[src^="http://www.pornhub.com/album/strange/"] imagewaste.com##img[style="border: 2px solid ; width: 160px; height: 135px;"] imagewaste.com##img[style="border: 2px solid ; width: 162px; height: 135px;"] soniared.org##img[width="120"] lukeisback.com##img[width="140"][height="525"] loralicious.com##img[width="250"] 171gifs.com##img[width="250"][height="1000"] loralicious.com##img[width="300"] 4sex4.com##img[width="300"][height="244"] 171gifs.com,efukt.com,pornhub.com##img[width="300"][height="250"] naughty.com##img[width="450"] adultwork.com,babepicture.co.uk,imagetwist.com,naughty.com,sexmummy.com,tophentai.biz,tvgirlsgallery.co.uk,veronika-fasterova.cz,victoriarose.eu##img[width="468"] clips4sale.com##img[width="468px"] anetakeys.net,angelinacrow.org,cherryjul.eu,madisonparker.eu,nikkythorne.com,sexysandra.eu,sharkablue.eu,vanessasmoke.net##img[width="500"] 171gifs.com##img[width="500"][height="150"] 171gifs.com##img[width="500"][height="180"] 171gifs.com##img[width="640"][height="90"] fleshasiadaily.com##img[width="700"] 171gifs.com,babeshows.co.uk##img[width="728"][height="90"] mofosex.com##li[style="width: 385px; height: 380px; display: block; float: right;"] picfoco.com##table[border="0"][width="728"] xcritic.com##table[cellpadding="10"][width="600"] xnxx.com##table[cellspacing="3"][width="930"] xnxx.com,xvideos.com##table[height="244"][width="930"] homemademoviez.com##table[height="450"][width="600"] xvideos.com##table[height="480"] loadsofpics.com##table[height="750"] imagewaste.com##table[style="width: 205px; height: 196px;"] starcelebs.com##table[style="width:218px; border-width:1px; border-style:solid; border-color:black; border-collapse: collapse"] pornper.com,xxxkinky.com##table[width="100%"][height="260"] taxidrivermovie.com##table[width="275"] xvideos.com##table[width="342"] humoron.com##table[width="527"] exgfpics.com##table[width="565"] xcritic.com##table[width="610"][height="150"] imagecarry.com##table[width="610"][height="260"] milkmanbook.com##table[width="620"] free-adult-anime.com##table[width="620"][cellspacing="1"][cellpadding="4"][bordercolor="#FF33FF"][border="0"] amateuralbum.net##table[width="722"] hotlinkimage.com##table[width="728"] exgfpics.com##table[width="750"][height="248"] grannysexforum.com##table[width="768"][height="226"] titsintops.com##table[width="780"] newsfilter.org##table[width="800px"] anyvids.com##table[width="860"][cellspacing="1"][cellpadding="10"][border="1"] xnxx.com##table[width="900"][height="244"] magnetxxx.com##table[width="900"][height="250"] xxvideo.us##table[width="950"][height="252"] petiteteenager.com##table[width="960"][height="102"] homemademoviez.com##table[width="980"] boobieblog.com##td[align="center"][width="20%"] skimtube.com##td[align="center"][width="330"] rude.com##td[height="25"] furnow.com##td[height="300"][align="center"] motherless.com##td[style="padding-top: 10px; padding-left: 2px; padding-right: 4px;"] ezilon.com##td[width="120"][align="center"] asianforumer.com##td[width="160"][valign="top"][align="left"] sharks-lagoon.fr##td[width="164"][valign="top"][bgcolor="#3366ff"][align="center"] xvideos.com##td[width="180"] imagedunk.com##td[width="250"] imagedax.net##td[width="300"] xhamster.com##td[width="360"] pornwikileaks.com##td[width="43"] tube8.com##topadblock !-----------------------Whitelists to fix broken sites------------------------! ! *** easylist:easylist/easylist_whitelist.txt *** @@.com/b/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@.com/banners/$image,domain=catalogfavoritesvip.com|deliverydeals.co.uk|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@.com/image-*-$image,domain=affrity.com|catalogfavoritesvip.com|deliverydeals.co.uk|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|theperfectsaver.com|travelplus.com @@.net/image-*-$image,domain=affrity.com|catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@/advertising-glype/*$image,stylesheet @@/display-ad/*$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@/wordpress/wp-admin/*-ads-manager/*$~third-party @@/wordpress/wp-admin/*/adrotate/*$~third-party @@/wp-content/plugins/bwp-minify/min/?f=$script,stylesheet,~third-party @@||192.168.$xmlhttprequest @@||192.168.*/images/adv_ @@||196.30.218.174/admentor/sirius_sdo_top.htm$subdocument,domain=sharedata.co.za @@||196.30.218.174/admentor/top_$subdocument,domain=fundsdata.co.za @@||208.100.24.244^$script,domain=sankakucomplex.com @@||209.222.8.217/crossdomain.xml$object-subrequest,domain=~p2p.adserver.ip @@||247realmedia.com^*/farecomp/ @@||24ur.com/adserver/adall. @@||24ur.com/static/*/banners.js @@||2mdn.net/crossdomain.xml$domain=rte.ie @@||2mdn.net/instream/*/adsapi_$object-subrequest,domain=3news.co.nz|49ers.com|atlantafalcons.com|azcardinals.com|baltimoreravens.com|buccaneers.com|buffalobills.com|chargers.com|chicagobears.com|clevelandbrowns.com|colts.com|dallascowboys.com|denverbroncos.com|detroitlions.com|egirlgames.net|euronews.com|giants.com|globaltv.com|houstontexans.com|jaguars.com|kcchiefs.com|ktvu.com|miamidolphins.com|neworleanssaints.com|newyorkjets.com|packers.com|panthers.com|patriots.com|philadelphiaeagles.com|raiders.com|redskins.com|rte.ie|seahawks.com|steelers.com|stlouisrams.com|thecomedynetwork.ca|titansonline.com|vikings.com|wpcomwidgets.com @@||2mdn.net/instream/flash/*/adsapi.swf$object-subrequest @@||2mdn.net/instream/html5/ima3.js @@||2mdn.net/instream/video/client.js$domain=cbc.ca @@||2mdn.net/viewad/*/B*_$image,domain=jabong.com @@||2mdn.net^*/jwplayer.js$domain=doubleclick.net @@||2mdn.net^*/player.swf$domain=doubleclick.net @@||33universal.adprimemedia.com/vn/vna/data/ad.php?$object-subrequest @@||360gig.com/images/1_468x60.png @@||4cdn.org/adv/$image,domain=4chan.org @@||53.com/resources/images/ad-rotator/ @@||6waves.com/ads/720x300/ @@||6waves.com/js/adshow.js @@||961bobfm.com/Pics/Ad%20Images/LISTEN_LIVE_BUTTON.png @@||9msn.com.au/Services/Service.axd?callback=ninemsn_ads_contextualTargeting_$script,domain=ninemsn.com.au @@||9msn.com.au/share/com/adtrack/adtrack.js$domain=ninemsn.com.au @@||9msn.com.au^*/ads/ninemsn.ads$script @@||a.giantrealm.com/assets/vau/grplayer*.swf @@||a.intentmedia.net/adServer/$script,domain=hotwire.com @@||abbyy.com/adx/$~third-party @@||abc.com/streaming/ads/preroll_$object-subrequest,domain=abc.go.com @@||abcnews.com/assets/static/ads/fwps.js @@||abcnews.go.com/assets/static/ads/fwps.js @@||activelydisengaged.com/wp-content/uploads/*/ad$image @@||ad.103092804.com/st?ad_type=$subdocument,domain=wizard.mediacoderhq.com @@||ad.71i.de/crossdomain.xml$object-subrequest @@||ad.71i.de/global_js/magic/sevenload_magic.js$object-subrequest @@||ad.adorika.com/st?ad_type=ad&ad_size=728x90$script,domain=lshunter.tv @@||ad.adserve.com/crossdomain.xml$object-subrequest @@||ad.afy11.net/crossdomain.xml$object-subrequest @@||ad.doubleclick.net/ad/*.JABONG.COM$image,domain=jabong.com @@||ad.doubleclick.net/ad/can/cbs/*;pausead=1;$object-subrequest @@||ad.doubleclick.net/adi/*.JABONG.COM$document,subdocument,domain=jabong.com @@||ad.doubleclick.net/adj/*/cartalk.audio_player;$script,domain=cartalk.com @@||ad.doubleclick.net/adj/rstone.site/music/photos^$script,domain=rollingstone.com @@||ad.doubleclick.net/adx/nbcu.nbc/rewind$object-subrequest @@||ad.doubleclick.net/clk;*?https://dm.victoriassecret.com/product/$image,domain=freeshipping.com @@||ad.doubleclick.net/N7175/adj/fdc.forbes/welcome;id=fdc/welcome;pos=thoughtx;$script,domain=forbes.com @@||ad.doubleclick.net/pfadx/nbcu.nbc/rewind$object-subrequest @@||ad.ghfusion.com/constants.js$domain=gamehouse.com @@||ad.reebonz.com/www/ @@||ad.smartclip.net/crossdomain.xml$object-subrequest @@||ad.wsod.com^$domain=scottrade.com @@||ad.zanox.com/ppc/$subdocument,domain=wisedock.at|wisedock.co.uk|wisedock.com|wisedock.de|wisedock.eu @@||ad2.zophar.net/images/logo.jpg$image @@||ad3.eu^$~third-party @@||ad4.liverail.com/?compressed|$domain=majorleaguegaming.com|pbs.org|wikihow.com @@||ad4.liverail.com/?LR_ORDER_ID=$object-subrequest,domain=volarvideo.com @@||ad4.liverail.com/?LR_PUBLISHER_ID=$object-subrequest,domain=playreplay.net @@||ad4.liverail.com/crossdomain.xml$object-subrequest @@||ad4.liverail.com/|$object-subrequest,domain=bizu.tv|foxsports.com.au|majorleaguegaming.com|pbs.org|wikihow.com @@||ad4.liverail.com/|$xmlhttprequest,domain=c.brightcove.com @@||ad4.liverail.com^*LR_VIDEO_ID=$object-subrequest,domain=bizu.tv @@||ad4game.com/ima3_preloader_*.swf$object,domain=escapefan.com @@||ad4game.com/www/delivery/video.php?zoneid=$script,domain=escapefan.com @@||adap.tv/control?$object-subrequest @@||adap.tv/crossdomain.xml$object-subrequest @@||adap.tv/redir/client/adplayer.swf$object-subrequest @@||adap.tv/redir/client/static/as3adplayer.swf$object-subrequest,domain=blogtalkradio.com|britannica.com|collegehumor.com|freeonlinegames.com|openfilmpod.com|stickam.com|talkingpointsmemo.com|thesource.com|wildearth.tv|wunderground.com @@||adap.tv/redir/client/swfloader.swf?$domain=box10.com|freeonlinegames.com|games.aarp.org|kizi.com|latimes.com|merriam-webster.com|puzzles.usatoday.com @@||adap.tv/redir/javascript/adaptvAdPlayer.js$domain=yepi.com @@||adap.tv/redir/javascript/vpaid.js @@||adap.tv/redir/plugins/*/adotubeplugin.swf?$domain=stickam.com @@||adbar.pp.ua^$~third-party @@||adblockplus.org^$elemhide,domain=easylist.adblockplus.org|reports.adblockplus.org @@||adboost.io^$~third-party @@||adbureau.net^*/images/adselector/$domain=brisbanetimes.com.au|smh.com.au|theage.com.au|watoday.com.au @@||adcode.mobi^$~third-party @@||addictinggames.com^*/mtvi_ads_reporting.js @@||adevents.com.au^$~third-party @@||adf.ly/images/ad*.png @@||adf.ly/static/image/ad_top_bg.png @@||adfarm.mediaplex.com^$domain=afl.com.au @@||adflyer.co.uk/adverts/$image @@||adgear.com^*/adgear.js$domain=lifemadedelicious.ca|tac.tv @@||adguard.com^$~third-party @@||adhostingsolutions.com/crossdomain.xml$object-subrequest @@||adimages.go.com/crossdomain.xml$object-subrequest @@||adm.fwmrm.net^*/AdManager.js$domain=msnbc.com|sky.com @@||adm.fwmrm.net^*/BrightcovePlugin.js$domain=9jumpin.com.au|9news.com.au|bigbrother.com.au|ninemsn.com.au @@||adm.fwmrm.net^*/LinkTag2.js$domain=6abc.com|7online.com|abc11.com|abc13.com|abc30.com|abc7.com|abc7chicago.com|abc7news.com|ahctv.com|animalplanet.com|destinationamerica.com|discovery.com|discoverylife.com|tlc.com @@||adm.fwmrm.net^*/TremorAdRenderer.$object-subrequest,domain=go.com @@||adm.fwmrm.net^*/videoadrenderer.$object-subrequest,domain=cnbc.com|espnfc.co.uk|espnfc.com|espnfc.com.au|espnfc.us|espnfcasia.com|go.com|nbc.com @@||adman.se^$~third-party @@||admedia.wsod.com^$domain=scottrade.com @@||admin.brightcove.com/viewer/*/brightcovebootloader.swf?$object,domain=gamesradar.com @@||adnet.mennonite.net^$domain=adnetonline.org @@||adnet.twitvid.com/crossdomain.xml$object-subrequest @@||adnews.pl^$~third-party @@||adotube.com/adapters/as3overstream*.swf?$domain=livestream.com @@||adotube.com/crossdomain.xml$object-subrequest @@||adpages.com^$~third-party @@||adphoto.eu^$~third-party @@||adroll.com/j/roundtrip.js$domain=onehourtranslation.com @@||ads.adap.tv/applist|$object-subrequest,domain=wunderground.com @@||ads.ahds.ac.uk^$~document @@||ads.awadserver.com^$domain=sellallautos.com @@||ads.badassembly.com^$~third-party @@||ads.belointeractive.com/realmedia/ads/adstream_mjx.ads/www.kgw.com/video/$script @@||ads.bizx.info/www/delivery/spc.php?zones$script,domain=nyctourist.com @@||ads.bridgetrack.com/ads_v2/script/btwrite.js$domain=ads.bridgetrack.com @@||ads.cnn.com/js.ng/*&cnn_intl_subsection=download$script @@||ads.ehealthcaresolutions.com/tag/$domain=familydoctor.org @@||ads.eu.com/ads-$~third-party @@||ads.expedia.com/event.ng/type=click&$domain=expedia.com @@||ads.forbes.com/realmedia/ads/*@videopreroll$script @@||ads.fox.com/fox/black_2sec_600.flv @@||ads.foxnews.com/api/*-slideshow-data.js? @@||ads.foxnews.com/js/ad.js @@||ads.foxnews.com/js/adv2.js @@||ads.foxnews.com/js/omtr_code.js @@||ads.fusac.fr^$~third-party @@||ads.globo.com^*/globovideo/player/ @@||ads.golfweek.com^$~third-party @@||ads.healthline.com/v2/adajax?$subdocument @@||ads.intergi.com/adrawdata/*/ADTECH;$object-subrequest,domain=melting-mindz.com @@||ads.intergi.com/crossdomain.xml$object-subrequest @@||ads.jetpackdigital.com.s3.amazonaws.com^$image,domain=vibe.com @@||ads.jetpackdigital.com/jquery.tools.min.js?$domain=vibe.com @@||ads.jetpackdigital.com^*/_uploads/$image,domain=vibe.com @@||ads.m1.com.sg^$~third-party @@||ads.mefeedia.com/flash/flowplayer-3.1.2.min.js @@||ads.mefeedia.com/flash/flowplayer.controls-3.0.2.min.js @@||ads.mycricket.com/www/delivery/ajs.php?zoneid=$script,~third-party @@||ads.nyootv.com/crossdomain.xml$object-subrequest @@||ads.nyootv.com:8080/crossdomain.xml$object-subrequest @@||ads.pandora.tv/netinsight/text/pandora_global/channel/icf@ @@||ads.pinterest.com^$~third-party @@||ads.pointroll.com/PortalServe/?pid=$xmlhttprequest,domain=thestreet.com @@||ads.reempresa.org^$domain=reempresa.org @@||ads.seriouswheels.com^$~third-party @@||ads.simplyhired.com^$domain=simply-partner.com|simplyhired.com @@||ads.smartfeedads.com^$~third-party @@||ads.socialtheater.com^$~third-party @@||ads.songs.pk/openx/www/delivery/ @@||ads.spilgames.com/ad/$script,domain=games.co.uk @@||ads.sudpresse.be/adview.php?what=zone:$image @@||ads.tbs.com/html.ng/site=*600x400_$domain=tbs.com @@||ads.trackitdown.net/delivery/afr.php?zoneid=6&$subdocument,~third-party @@||ads.trutv.com/crossdomain.xml$object-subrequest @@||ads.trutv.com/html.ng/tile=*&site=trutv&tru_tv_pos=preroll&$object-subrequest @@||ads.undertone.com/*&zoneid=$domain=mlbtraderumors.com @@||ads.undertone.com/crossdomain.xml$object-subrequest @@||ads.yimg.com/a/$domain=autos.yahoo.com @@||ads.yimg.com/ev/eu/any/vint/videointerstitial*.js @@||ads.yimg.com/la/adv/y/yahooxtra$image,domain=movies.yahoo.com @@||ads.yimg.com^*/any/yahoologo$image @@||ads.yimg.com^*/search/b/syc_logo_2.gif @@||ads.yimg.com^*videoadmodule*.swf @@||ads1.msads.net^*/dapmsn.js$domain=msn.com @@||ads1.msn.com/ads/pronws/$image @@||ads1.msn.com/library/dap.js$domain=entertainment.msn.co.nz|msn.foxsports.com @@||adsbox.com.sg^$~third-party @@||adsbox.in^$~third-party @@||adseo.pl^$~third-party @@||adserver.adtech.de/?adrawdata$script,domain=we7.com @@||adserver.adtech.de/?advideo/*;vidas=pre_roll^$object-subrequest,domain=eurovisionsports.tv|talksport.co.uk|wrc.com @@||adserver.adtech.de/addyn/3.0/755/$domain=cartoonnetwork.co.nz|cartoonnetworkasia.com|cartoonnetworkhq.com|manutd.com @@||adserver.adtechus.com/addyn/$script,domain=teletoon.com @@||adserver.bigwigmedia.com/adfetch2.php?$object-subrequest,domain=y8.com @@||adserver.bigwigmedia.com/ingamead3.swf @@||adserver.bworldonline.com^ @@||adserver.tvcatchup.com^$object-subrequest @@||adserver.vidcoin.com^*/get_campaigns?$xmlhttprequest @@||adserver.yahoo.com/a?*&l=head&$script,domain=yahoo.com @@||adserver.yahoo.com/a?*&l=VID&$xmlhttprequest,domain=yahoo.com @@||adserver.yahoo.com/a?*=headr$script,domain=mail.yahoo.com @@||adserver.yahoo.com/crossdomain.xml$object-subrequest @@||adserver.yahoo.com^*=weather&$domain=ca.weather.yahoo.com @@||adshost1.com/crossdomain.xml$object-subrequest @@||adshost1.com/ova/*.xml$object-subrequest,domain=4shared.com @@||adsign.republika.pl^$subdocument,domain=a-d-sign.pl @@||adsign.republika.pl^$~third-party @@||adsonar.com/js/adsonar.js$domain=ansingstatejournal.com|app.com|battlecreekenquirer.com|clarionledger.com|coloradoan.com|dailyrecord.com|dailyworld.com|delmarvanow.com|freep.com|greatfallstribune.com|guampdn.com|hattiesburgamerican.com|hometownlife.com|ithacajournal.com|jconline.com|livingstondaily.com|montgomeryadvertiser.com|mycentraljersey.com|news-press.com|pal-item.com|pnj.com|poughkeepsiejournal.com|press-citizen.com|pressconnects.com|rgj.com|shreveporttimes.com|stargazette.com|tallahassee.com|theadvertiser.com|thecalifornian.com|thedailyjournal.com|thenewsstar.com|thestarpress.com|thetimesherald.com|thetowntalk.com|visaliatimesdelta.com @@||adsonar.com/js/aslJSON.js$domain=engadget.com @@||adspot.lk^$~third-party @@||adsremote.scrippsnetworks.com/crossdomain.xml$object-subrequest @@||adsremote.scrippsnetworks.com/html.ng/adtype=*&playertype=$domain=gactv.com @@||adsremote.scrippsnetworks.com/js.ng/adtype=vsw$script,domain=food.com @@||adssecurity.com/app_themes/ads/images/ @@||adswizz.com/www/components/$object-subrequest,domain=motogp.com @@||adswizz.com/www/delivery/swfindex.php?reqtype=adssetup&$object-subrequest,domain=motogp.com @@||adtech.de/?advideo/3.0/1215.1/3228528/*;vidas=pre_roll;$object-subrequest @@||adtech.de/apps/*.swf?targettag=$object,domain=cartoonnetworkasia.com @@||adtech.de/crossdomain.xml$object-subrequest,domain=~zattoo.com @@||adtechus.com/?advideo/$domain=snagfilms.com @@||adtechus.com/apps/$image,domain=teletoon.com|walmart.ca @@||adtechus.com/crossdomain.xml$object-subrequest @@||adtechus.com/dt/common/DAC.js$domain=wetpaint.com @@||adultvideotorrents.com/assets/blockblock/advertisement.js @@||adv.*.przedsiebiorca.pl^$~third-party @@||adv.blogupp.com^ @@||adv.erti.se^$~third-party @@||adv.escreverdireito.com^$~third-party @@||adv.li^$~third-party @@||advantabankcorp.com/ADV/$~third-party @@||advertise.azcentral.com^$~third-party @@||advertise.fairfaxmedia.com.au^$domain=fairfaxmedia.com.au|myfairfax.com.au @@||advertise.movem.co.uk^$~third-party @@||advertiser.seek.co.nz^$~third-party @@||advertiser.seek.com.au^$~third-party @@||advertiser.trialpay.com^$~third-party @@||advertisers.io^$domain=advertisers.io @@||advertising.acne.se^$~third-party @@||advertising.autotrader.co.uk^$~third-party @@||advertising.racingpost.com^$image,script,stylesheet,~third-party,xmlhttprequest @@||advertising.scoop.co.nz^ @@||advertising.theigroup.co.uk^$~third-party @@||advertising.utexas.edu^$~third-party @@||advertising.vrisko.gr^$~third-party @@||adverts.brighthouse.com/advertpro/servlet/view/banner/url/zone?*=preroll/2Black|$subdocument,domain=baynews9.com|cfnews13.com @@||adverts.cdn.tvcatchup.com^$object-subrequest @@||adverts.we7c.net/config/live/newusertraffickingconfig.json?$script,domain=we7.com @@||advisory.mtanyct.info/outsideWidget/widget.html?*.adPlacement=$subdocument @@||adweb.cis.mcmaster.ca^$~third-party @@||adweb.pl^$~third-party @@||adworks.com.co^$~third-party @@||ae.amgdgt.com/ads?t=$object-subrequest,domain=nfl.com @@||ae.amgdgt.com/crossdomain.xml$object-subrequest @@||affiliate.$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||affiliate.kickapps.com/crossdomain.xml$object-subrequest @@||affiliate.kickapps.com/service/ @@||affiliate.skiamade.com^$subdocument,third-party @@||affiliates.$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||affiliates.mozilla.org^$subdocument,domain=facebook.com @@||affiliates.unpakt.com/widget/$subdocument @@||affiliates.unpakt.com/widget_loader/widget_loader.js @@||africam.com/adimages/ @@||aimsworldrunning.org/images/AD_Box_$image,~third-party @@||airbaltic.com/banners/$~third-party @@||airguns.net/advertisement_images/ @@||airguns.net/classifieds/ad_images/ @@||airplaydirect.com/openx/www/images/$image @@||aiwip.com/advertisers/$image,~third-party,xmlhttprequest @@||aiwip.com/static/images/advertisers/$image,~third-party,xmlhttprequest @@||ajmadison.com/images/adverts/ @@||aka-cdn-ns.adtech.de/apps/$object-subrequest,domain=manutd.com @@||akamai.net^*/ads/preroll_$object-subrequest,domain=bet.com @@||akamai.net^*/i.mallnetworks.com/images/*120x60$domain=ultimaterewardsearn.chase.com @@||akamai.net^*/pics.drugstore.com/prodimg/promo/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||akamaihd.net/hads-*.mp4? @@||akamaihd.net^*/videoAd.js$domain=zynga.com @@||al.com/static/common/js/ads/ads.js @@||albumartexchange.com/gallery/images/public/ad/$image @@||allot.com/Banners/*.swf$object @@||allulook4.com/min/?$stylesheet @@||alphabaseinc.com/images/display_adz/$~third-party @@||alusa.org/store/modules/blockadvertising/$~third-party @@||amazon-adsystem.com/aax2/amzn_ads.js$domain=deadspin.com|gawker.com|gizmodo.com|io9.com|jalopnik.com|jezebel.com|kotaku.com|lifehacker.com|weather.com @@||amazon-adsystem.com/e/cm?t=englcultrevi-21&$document,subdocument,domain=englishculturalrevival.com @@||amazon-adsystem.com/widgets/q?$image,domain=choose-one.com @@||amazon-adsystem.com^$document,subdocument,domain=affrity.com @@||amazon-adsystem.com^$domain=affrity.com @@||amazon.com/widgets/$domain=sotumblry.com @@||amazonaws.com/adplayer/player/newas3player.swf?$object,domain=india.com @@||amazonaws.com/banners/$image,domain=livefromdarylshouse.com|pandasecurity.com @@||amazonaws.com/bt-dashboard-logos/$domain=signal.co @@||amazonaws.com^*/sponsorbanners/$image,domain=members.portalbuzz.com @@||amctv.com/commons/advertisement/js/AdFrame.js @@||amiblood.com/Images/ad.jpg @@||amwa.net/sites/default/files/styles/promotion_image/public/promotions/$~third-party @@||ananzi.co.za/ads/$~third-party @@||andcorp.com.au^*.swf?clicktag= @@||andohs.net/crossdomain.xml$object-subrequest @@||andomediagroup.com/crossdomain.xml$object-subrequest @@||annfammed.org/adsystem/$image,~third-party @@||aolcdn.com/ads/adsWrapper.js$domain=aol.com|engadget.com|games.com|huffingtonpost.com|mapquest.com|stylelist.ca @@||aolcdn.com/ads/adsWrapperIntl.js$domain=huffingtonpost.co.uk @@||aolcdn.com/os_merge/?file=/aol/*.js&$script @@||aolcdn.com^*/adhads.css$domain=aol.com @@||aone-soft.com/style/images/ad*.jpg @@||api.cirqle.nl^*&advertiserId=$script,xmlhttprequest @@||api.hexagram.com^$domain=scribol.com @@||api.paymentwall.com^$domain=adguard.com @@||apmebf.com/ad/$domain=betfair.com @@||apmebf.com^$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||apmex.com/resources/ads/ @@||app.promo.tubemogul.com/feed/placement.html?id=$script,domain=comedy.com @@||apple.com^*/ads/$object,object-subrequest,xmlhttprequest @@||apple.com^*/images/ad-$image,domain=apple.com @@||apple.com^*/images/ads_$image,domain=apple.com @@||apple.com^*/includes/ads @@||apple.com^*/video-ad.html @@||applegate.co.uk/stats/recordclick.html?$xmlhttprequest @@||apps.digmyweb.com/ads?$xmlhttprequest @@||apwg.org/images/sponsors/ @@||archaeologydataservice.ac.uk/images/ads_$image @@||archiproducts.com/adv/ @@||architecturaldigest.com/etc/designs/ad/images/shell/ad-sprite.png @@||area51.stackexchange.com/ads/$image @@||arti-mediagroup.com/crossdomain.xml$object-subrequest @@||arti-mediagroup.com/flowplayer/amta_plugin.swf$object-subrequest @@||as.bankrate.com/RealMedia/ads/adstream_mjx.ads/$script,~third-party @@||as.medscape.com/html.ng/transactionid%$subdocument,domain=medscape.com @@||as.webmd.com/html.ng/transactionid=$object-subrequest,script,subdocument @@||asiasold.com/assets/home/openx/$image,~third-party @@||asrock.com/images/ad-$~third-party @@||assets.rewardstyle.com^$domain=glamour.com|itsjudytime.com @@||assiniboine.mb.ca/files/intrasite_ads/ @@||assoc-amazon.com/widgets/$domain=sotumblry.com @@||assoc-amazon.com^*/js/swfobject_$domain=gactv.com @@||asterisk.org/sites/asterisk/files/mce_files/graphics/ads/ad-training.png @@||athena365.com/web/components/ads/rma.html @@||att.com/images/*/admanager/ @@||au.adserver.yahoo.com/a?$subdocument,domain=dating.yahoo.com.au @@||auditude.com/adserver?$object-subrequest,domain=ap.org|majorleaguegaming.com|newsinc.com @@||auditude.com/crossdomain.xml$object-subrequest @@||auditude.com^*/AuditudeAdUnit.swf$object-subrequest @@||auditude.com^*/auditudebrightcoveplugin.swf$object-subrequest,domain=channel5.com @@||auditude.com^*/auditudeosmfproxyplugin.swf$object-subrequest,domain=dramafever.com|majorleaguegaming.com @@||autogespot.info/upload/ads/$image @@||autotrader.co.uk/advert/$xmlhttprequest @@||autotrader.co.uk/static/*/images/adv/icons.png @@||autotrader.co.uk^*/advert/$~third-party,xmlhttprequest @@||autotrader.co.uk^*_adverts/$xmlhttprequest @@||avclub.com/ads/av-video-ad/$xmlhttprequest @@||aviationclassifieds.com/adimg/$image,~third-party @@||aviationdocumentstorage.com/Av_Docs/CSS/ADS-1.css @@||aviationexplorer.com/airline_aviation_ads/ @@||awin1.com/cshow.php?s=$image,domain=deliverydeals.co.uk @@||awltovhc.com^$object,domain=affrity.com @@||backpackinglight.com/backpackinglight/ads/banner-$~third-party @@||bafta.org/static/site/javascript/banners.js @@||bahtsold.com/assets/home/openx/Thailand/$image,~third-party @@||bahtsold.com/assets/images/ads/no_img_main.png @@||bankofamerica.com^*?adx=$xmlhttprequest @@||banner.pumpkinpatchkids.com/www/delivery/$domain=pumpkinpatch.co.nz|pumpkinpatch.co.uk|pumpkinpatch.com|pumpkinpatch.com.au @@||banner4five.com/banners/$~third-party @@||bannerfans.com/banners/$image,~third-party @@||bannerist.com/images/$image,domain=bannerist.com @@||banners.gametracker.rs^$image @@||banners.goldbroker.com/widget/ @@||banners.wunderground.com^$image @@||bannersnack.net^$domain=bannersnack.com @@||barafranca.*/banner.php| @@||bbc.co.uk^*/adsense_write.js$domain=bbc.com @@||bbc.co.uk^*/advert.js$domain=bbc.com @@||bbc.co.uk^*/adverts.js$domain=bbc.com @@||bbci.co.uk^*/adsense_write.js$domain=bbc.com @@||bbci.co.uk^*/adverts.js$domain=bbc.co.uk|bbc.com @@||bbcimg.co.uk^*/adsense_write.js$domain=bbc.com @@||bbcimg.co.uk^*/advert.js$domain=bbc.co.uk|bbc.com @@||bbcimg.co.uk^*/adverts.js$domain=bbc.co.uk|bbc.com @@||bbcimg.co.uk^*/SmpAds.swf$object-subrequest,domain=bbc.com @@||beatthebrochure.com/js/jquery.popunder.js @@||bebusiness.eu/js/adview.js @@||bellaliant.net^*/banners/ads/$image,~third-party @@||betar.gov.bd/wp-content/plugins/useful-banner-manager/ @@||betar.gov.bd/wp-content/uploads/useful_banner_manager_banners/ @@||betteradvertising.com/logos/$image,domain=ghostery.com @@||bigfishaudio.com/banners/$image @@||bikeexchange.com.au/adverts/ @@||bing.com/images/async?q=$xmlhttprequest @@||bing.com/maps/Ads.ashx$xmlhttprequest @@||bing.net/images/thumbnail.aspx?q=$image @@||blackshoppingchannel.com^*/ad_agency/$~third-party @@||blackshoppingchannel.com^*/com_adagency/$~third-party @@||blastro.com/pl_ads.php?$object-subrequest @@||bloomberg.com/rapi/ads/js_config.js @@||bluetooth.com/banners/ @@||bluetree.co.uk/hji/advertising.$object-subrequest @@||bnbfinder.com/adv_getCity.php?$xmlhttprequest @@||boats.com/ad/$~third-party,xmlhttprequest @@||bonappetit.com/ams/page-ads.js? @@||bonappetit.com^*/cn.dart.js @@||boracay.mobi/boracay/imageAds/$image,domain=boracay.tel @@||boston.com/images/ads/yourtown_social_widget/$image @@||box10.com/advertising/*-preroll.swf @@||boxedlynch.com/advertising-gallery.html @@||brainient.com/crossdomain.xml$object-subrequest @@||brightcove.com^*bannerid$third-party @@||britannica.com/resources/images/shared/ad-loading.gif @@||britishairways.com/cms/global/styles/*/openx.css @@||brocraft.net/js/banners.js @@||brothersoft.com/gads/coop_show_download.php?soft_id=$script @@||bsvideos.com/json/ad.php? @@||bthomehub.home/images/adv_ @@||btrll.com/crossdomain.xml$object-subrequest @@||btrll.com/vast/$object-subrequest,domain=nfl.com @@||burbankleader.com/hive/images/adv_ @@||burfordadvertising.com/advertising/$~third-party @@||business-supply.com/images/adrotator/ @@||butlereagle.com/static/ads/ @@||buy.com/buy_assets/addeals/$~third-party @@||buyandsell.ie/ad/$~third-party @@||buyandsell.ie/ads/$~third-party @@||buyandsell.ie/images/ads/$~third-party @@||buyforlessok.com/advertising/ @@||buyselltrade.ca/adimages/$image,~third-party @@||bworldonline.com/adserver/ @@||cache.nymag.com/scripts/ad_manager.js @@||cameralabs.com/PG_library/Regional/US/Love_a_Coffee_120x240.jpg @@||campingworld.com/images/AffiliateAds/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||canadianlisted.com/css/*/ad/index.css @@||candystand.com/assets/images/ads/$image @@||capitalone360.com/js/adwizard/adwizard_homepage.js? @@||caranddriver.com/tools/iframe/?$subdocument @@||carzone.ie/es-ie/*advert$image,script,stylesheet @@||cas.clickability.com/cas/cas.js?r=$script,domain=kmvt.com @@||cbc.ca/ads/*.php?$xmlhttprequest @@||cbs.com/sitecommon/includes/cacheable/combine.php?*/adfunctions. @@||cbsistatic.com/cnwk.1d/ads/common/manta/adfunctions*.js$domain=cnettv.cnet.com @@||cbslocal.com/flash/videoads.*.swf$object,domain=radio.com @@||cc-dt.com/link/tplimage?lid=$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||cdn.betrad.com/pub/icon1.png$domain=usanetwork.com @@||cdn.complexmedianetwork.com/cdn/agenda.complex.com/js/jquery.writecapture.js @@||cdn.complexmedianetwork.com/cdn/agenda.complex.com/js/jwplayerl.js @@||cdn.complexmedianetwork.com/cdn/agenda.complex.com/js/swfobject.js @@||cdn.complexmedianetwork.com/cdn/agenda.complex.com/js/writecapture.js @@||cdn.cpmstar.com/cached/js/$script,domain=xfire.com @@||cdn.cpmstar.com/cached/swf/preplay.swf$object,domain=xfire.com @@||cdn.inskinmedia.com/*inskinfiles/flvs/$object-subrequest,domain=tvcatchup.com @@||cdn.inskinmedia.com/isfe/4.1/swf/unitcontainer2.swf$domain=tvcatchup.com @@||cdn.inskinmedia.com^*/brightcove3.js$domain=virginmedia.com @@||cdn.inskinmedia.com^*/ipcgame.js?$domain=mousebreaker.com @@||cdn.intentmedia.net^$image,script,domain=travelzoo.com @@||cdn.pch.com/spectrummedia/spectrum/adunit/ @@||cdn.travidia.com/fsi-page/$image @@||cdn.travidia.com/rop-ad/$image @@||cdn.travidia.com/rop-sub/$image @@||cdn.turner.com^*/video/336x280_ad.gif @@||cdn.vdopia.com^$object,object-subrequest,script,domain=indiatvnews.com|intoday.in|moneycontrol.com @@||cellc.co.za/adserv/$image,object,script,~third-party @@||cerebral.s4.bizhat.com/banners/$image,~third-party @@||channel4.com/media/scripts/oasconfig/siteads.js @@||charlieandmekids.com/www/delivery/$script,domain=charlieandmekids.co.nz|charlieandmekids.com.au @@||chase.com/content/*/ads/$image,~third-party @@||chase.com^*/adserving/ @@||cheapoair.ca/desktopmodules/adsales/adsaleshandle.ashx?$xmlhttprequest @@||cheapoair.com/desktopmodules/adsales/adsaleshandle.ashx?$xmlhttprequest @@||checkerdist.com/product-detail.cfm?*advert_id=$~third-party @@||checkm8.com/adam/$script,domain=askqology.com @@||checkm8.com/crossdomain.xml$object-subrequest @@||chemistwarehouse.com.au/images/AdImages/ @@||chibis.adotube.com/appruntime/player/$object,object-subrequest @@||chibis.adotube.com/appRuntime/swfobject/$script @@||chibis.adotube.com/napp/$object,object-subrequest @@||chicavenue.com.au/assets/ads/$image,~third-party @@||christianhouseshare.com.au/images/publish_ad1.jpg @@||cio.com/www/js/ads/gpt_includes.js @@||classifiedads.com/adbox.php$xmlhttprequest @@||classifieds.wsj.com/ad/$~third-party @@||classistatic.com^*/banner-ads/ @@||cleveland.com/static/common/js/ads/ads.js @@||clickbd.com^*/ads/$image,~third-party @@||cloudfront.net/_ads/$xmlhttprequest,domain=jobstreet.co.id|jobstreet.co.in|jobstreet.co.th|jobstreet.com|jobstreet.com.my|jobstreet.com.ph|jobstreet.com.sg|jobstreet.vn @@||club777.com/banners/$~third-party @@||clustrmaps.com/images/clustrmaps-back-soon.jpg$third-party @@||cnet.com/ad/ad-cookie/*?_=$xmlhttprequest @@||coastlinepilot.com/hive/images/adv_ @@||collective-media.net/crossdomain.xml$object-subrequest @@||collective-media.net/pfadx/wtv.wrc/$object-subrequest,domain=wrc.com @@||colorado.gov/airquality/psi/adv.png @@||comboadmedia.adperfect.com^$domain=classifieds.nydailynews.com @@||commarts.com/Images/missinganissue_ad.gif @@||completemarkets.com/pictureHandler.ashx?adid=$image,~third-party @@||computerworld.com/resources/scripts/lib/doubleclick_ads.js$script @@||comsec.com.au^*/homepage_banner_ad.gif @@||condenast.co.uk/scripts/cn-advert.js$domain=cntraveller.com @@||connectingdirectories.com/advertisers/$~third-party,xmlhttprequest @@||constructalia.com/banners/$image,~third-party @@||contactmusic.com/advertpro/servlet/view/dynamic/$object-subrequest @@||content.ad/images/$image,domain=wmpoweruser.com @@||content.datingfactory.com/promotools/$script @@||content.hallmark.com/scripts/ecards/adspot.js @@||copesdistributing.com/images/adds/banner_$~third-party @@||cosmopolitan.com/ams/page-ads.js @@||cosmopolitan.com/cm/shared/scripts/refreshads-$script @@||countryliving.com/ams/page-ads.js @@||cracker.com.au^*/cracker-classifieds-free-ads.$~document @@||cricbuzz.com/includes/ads/images/wct20/$image @@||cricbuzz.com/includes/ads/images/worldcup/more_arrow_$image @@||cricbuzz.com/includes/ads/schedule/$~third-party @@||cricketcountry.com/js/ad-gallery.js$script @@||csair.com/*/adpic.js @@||csmonitor.com/advertising/sharetools.php$subdocument @@||csoonline.com/js/doubleclick_ads.js? @@||css.washingtonpost.com/wpost/css/combo?*/ads.css @@||css.washingtonpost.com/wpost2/css/combo?*/ads.css @@||css.wpdigital.net/wpost/css/combo?*/ads.css @@||ctv.ca/players/mediaplayer/*/AdManager.js^ @@||cubeecraft.com/openx/$~third-party @@||cvs.com/webcontent/images/weeklyad/adcontent/$~third-party @@||cydiaupdates.net/CydiaUpdates.com_600x80.png @@||d1sp6mwzi1jpx1.cloudfront.net^*/advertisement_min.js$domain=reelkandi.com @@||d3con.org/data1/$image,~third-party @@||d3pkae9owd2lcf.cloudfront.net/mb102.js$domain=wowhead.com @@||da-ads.com/truex.html?$domain=deviantart.com @@||dailycaller.com/wp-content/plugins/advertisements/$script @@||dailyhiit.com/sites/*/ad-images/ @@||dailymail.co.uk^*/googleads--.js @@||dailymotion.com/videowall/*&clickTAG=http @@||dailypilot.com/hive/images/adv_ @@||danielechevarria.com^*/advertising-$~third-party @@||dart.clearchannel.com/crossdomain.xml$object-subrequest @@||data.panachetech.com/crossdomain.xml$object-subrequest @@||data.panachetech.com/|$object-subrequest,domain=southpark.nl @@||davescomputertips.com/images/ads/paypal.png @@||dawanda.com^*/ad_center.css$~third-party @@||dawanda.com^*/adcenter.js$~third-party @@||dc.tremormedia.com/crossdomain.xml$object-subrequest @@||dealerimg.com/Ads/$image @@||delicious.com^*/compose?url=$xmlhttprequest @@||deliciousdigital.com/data/our-work/advertising/ @@||delish.com/cm/shared/scripts/refreshads-*.js @@||delivery.anchorfree.us/player-multi.php?$subdocument,domain=anchorfree.us @@||delvenetworks.com/player/*_ad_$subdocument @@||demo.inskinmedia.com^$object-subrequest,domain=tvcatchup.com @@||deviantart.net/fs*/20*_by_$image,domain=deviantart.com @@||deviantart.net/minish/advertising/downloadad_splash_close.png @@||digiads.com.au/images/shared/misc/ad-disclaimer.gif @@||digsby.com/affiliate/banners/$image,~third-party @@||direct.fairfax.com.au/hserver/*/site=vid.*/adtype=embedded/$script @@||directorym.com/articles_media/$domain=localmarket.autismsupportnetwork.com @@||directtextbook.com^*.php?ad_ @@||discovery.com/components/consolidate-static/?files=*/adsense- @@||disney.com.au/global/swf/banner300x250.swf @@||disney.go.com/dxd/data/ads/game_ad.xml?gameid=$object-subrequest @@||disneyphotopass.com/adimages/ @@||disruptorbeam.com/assets/uploaded/ads/$image,~third-party @@||dmgt.grapeshot.co.uk^$domain=dailymail.co.uk @@||dmstatic.com^*/adEntry.js$domain=daft.ie @@||doityourself.com^*/shared/ads.css$stylesheet @@||dolidoli.com/images/ads- @@||dolimg.com^*/dxd_ad_code.swf$domain=go.com @@||dolphinimaging.com/banners.js @@||dolphinimaging.com/banners/ @@||domandgeri.com/banners/$~third-party @@||dotomi.com/commonid/match?$script,domain=betfair.com @@||doubleclick.net/ad/*.linkshare/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||doubleclick.net/ad/can/chow/$object-subrequest @@||doubleclick.net/ad/can/tvcom/$object-subrequest,domain=tv.com @@||doubleclick.net/adi/*.mlb/photos;*;sz=300x250;$subdocument,domain=mlb.com @@||doubleclick.net/adi/*.mlb/scoreboard;pageid=scoreboard_ymd;sz=$subdocument,domain=mlb.com @@||doubleclick.net/adi/amzn.*;ri=digital-music-track;$subdocument @@||doubleclick.net/adi/apts.com/home;pos=$subdocument,domain=apartments.com @@||doubleclick.net/adi/ebay.*/video;$subdocument,domain=ebay.com @@||doubleclick.net/adi/mlb.mlb/*;pageid=cutfour;sz=$subdocument,domain=mlb.mlb.com @@||doubleclick.net/adi/mlb.mlb/*^free_agent_tracker_12^$subdocument,domain=mlb.com @@||doubleclick.net/adi/sny.tv/media;$subdocument,domain=sny.tv @@||doubleclick.net/adi/sony.oz.opus/*;pos=bottom;$subdocument,domain=doctoroz.com @@||doubleclick.net/adi/yesnetwork.com/media;$subdocument,domain=yesnetwork.com @@||doubleclick.net/adi/zillow.hdp/$subdocument,domain=zillow.com @@||doubleclick.net/adj/bbccom.live.site.auto/*^sz=1x1^$script,domain=bbc.com @@||doubleclick.net/adj/cm.peo/*;cmpos=$script,domain=people.com @@||doubleclick.net/adj/cm.tim/*;cmpos=$script,domain=time.com @@||doubleclick.net/adj/ctv.muchmusicblog.com/$script @@||doubleclick.net/adj/gamesco.socialgaming/$script,domain=ghsrv.com @@||doubleclick.net/adj/imdb2.consumer.video/*;sz=320x240,$script @@||doubleclick.net/adj/kval/health;pos=gallerytop;sz=$script,domain=kval.com @@||doubleclick.net/adj/nbcu.nbc/videoplayer-$script @@||doubleclick.net/adj/oiq.man.$script,domain=manualsonline.com @@||doubleclick.net/adj/pch.candystand/video;pos=box;sz=300x250;a=$script,domain=candystand.com @@||doubleclick.net/adj/pong.all/*;dcopt=ist;$script @@||doubleclick.net/adj/profootballreference.fsv/$script,domain=pro-football-reference.com @@||doubleclick.net/adj/wiredcom.dart/*;sz=300x250;*;kw=top;$script,domain=wired.com @@||doubleclick.net/adj/yorkshire.jp/main-section;*;sz=120x600,160x600$script,domain=yorkshirepost.co.uk @@||doubleclick.net/ddm/clk/*://www.amazon.jobs/jobs/$subdocument,domain=glassdoor.com @@||doubleclick.net/N2605/adi/MiLB.com/scoreboard;*;sz=728x90;$subdocument @@||doubleclick.net/N6545/adj/*_music/video;$script,domain=virginmedia.com @@||doubleclick.net/N6619/adj/zillow.hdp/$script,domain=zillow.com @@||doubleclick.net/pfadx/*/cbs/$object-subrequest,domain=latimes.com @@||doubleclick.net/pfadx/nfl.*/html5;$xmlhttprequest,domain=nfl.com @@||doubleclick.net/pfadx/umg.*;sz=10x$script @@||doubleclick.net^*/ad/nfl.*.smartclip/$object-subrequest,domain=nfl.com @@||doubleclick.net^*/adi/MiLB.com/multimedia^$subdocument,domain=milb.com @@||doubleclick.net^*/adi/MiLB.com/standings^$subdocument,domain=milb.com @@||doubleclick.net^*/adj/wwe.shows/ecw_ecwreplay;*;sz=624x325;$script @@||doubleclick.net^*/fdc.forbes/*;pos=thought;$script,domain=forbes.com @@||doubleclick.net^*/ftcom.*;sz=1x1;*;pos=refresh;$script,domain=ft.com @@||doubleclick.net^*/ndm.tcm/video;$script,domain=player.video.news.com.au @@||doubleclick.net^*/targeted.optimum/*;sz=968x286;$image,popup,script @@||doubleclick.net^*/videoplayer*=worldnow$subdocument,domain=ktiv.com|wflx.com @@||dove.saymedia.com^$xmlhttprequest @@||downvids.net/ads.js @@||drf-global.com/servicegateway/globaltrips-shopping-svcs/drfadserver-1.0/pub/adserver.js?$domain=igougo.com|travelocity.com @@||drf-global.com/servicegateway/globaltrips-shopping-svcs/drfadserver-1.0/pub/drfcomms/advertisers?$script,domain=igougo.com|travelocity.com @@||drf-global.com/servicegateway/globaltrips-shopping-svcs/drfadserver-1.0/pub/drfcomms/drf?$script,domain=igougo.com|travelocity.com @@||drizzle.monsoonads.com/ip.php$object-subrequest,domain=bollywoodhungama.com @@||dropzone.no/sap/its/gfx/top_ad_$image,~third-party @@||drunkard.com/banners/drunk-korps-banner.jpg @@||drunkard.com/banners/drunkard-gear.jpg @@||drunkard.com/banners/modern-drunkard-book.jpg @@||drupal.org^*/revealads.png @@||dstw.adgear.com/crossdomain.xml$object-subrequest @@||dstw.adgear.com/impressions/int/as=*.json?ag_r=$object-subrequest,domain=hot899.com|nj1015.com|streamtheworld.com|tsn.ca @@||dwiextreme.com/banners/dwiextreme$image @@||dx.com/openx/$image,~third-party @@||dyncdn.buzznet.com/catfiles/?f=dojo/*.googleadservices.$script @@||eagleboys.com.au/eagleboys/*/ads/$~third-party @@||earthcam.com/swf/ads5.swf @@||earthtechling.com^*/imasters-wp-adserver-styles.css @@||earthtv.com/player_tmp/overlayad.js @@||easyfundraising.org.uk/images/home/*-120x60.$image @@||ebayrtm.com/rtm?rtmcmd&a=json&cb=parent.$script @@||eboundservices.com/iframe/newads/iframe.php?stream=$subdocument @@||economist.com.na^*/banners/cartoon_ @@||edgar.pro-g.co.uk/data/*/videos/adverts/$object-subrequest @@||edge.andomedia.com^*/ando/files/$object-subrequest,domain=radiou.com @@||edgesuite.net/general/ibn/ads/*.flv$object-subrequest,domain=ibnlive.in.com @@||edmontonjournal.com/js/adsync/adsynclibrary.js @@||eduspec.science.ru.nl^*-images/ad- @@||eeweb.com/comics/*_ads-$image @@||egotastic.us.intellitxt.com/intellitxt/front.asp @@||ehow.co.uk/frames/ad.html?$subdocument @@||eightinc.com/admin/zone.php?zoneid=$xmlhttprequest @@||elephantjournal.com/ad_art/ @@||eluxe.ca^*_doubleclick.js*.pagespeed.$script @@||emailbidding.com^*/advertiser/$~third-party,xmlhttprequest @@||emergencymedicalparamedic.com/wp-content/themes/AdSense/style.css @@||emjcd.com^$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||empireonline.com/images/image_index/300x250/ @@||engine.adzerk.net/ados?$script,domain=stackoverflow.com @@||englishanimes.com/wp-content/themes/englishanimes/js/pop.js @@||engrish.com/wp-content/uploads/*/advertisement-$image,~third-party @@||epicgameads.com/crossdomain.xml$object-subrequest @@||epicgameads.com/games/getSwfPath.php?$object-subrequest,domain=freewebarcade.com @@||epicgameads.com/games/mec_release_*.swf?$object-subrequest,domain=freewebarcade.com @@||eplayerhtml5.performgroup.com/js/tsEplayerHtml5/js/Eplayer/js/modules/bannerview/bannerview.main.js? @@||equippers.com/abm.aspx?$script @@||equippers.com/absolutebm.aspx?$script @@||espn.co.uk/ads/gamemodule_v0.2.swf$object @@||espn.go.com^*/espn360/banner?$subdocument @@||espncdn.com/combiner/*/admgr.$script,domain=espn.go.com @@||espncdn.com/combiner/c?*/ads.css$domain=espn.go.com @@||espncdn.com/combiner/c?*/advertising.$stylesheet,domain=espnfc.com @@||espngp.com/ads/*_sprite$domain=espnf1.com @@||esquire.com/ams/page-ads.js?$script @@||evanscycles.com/ads/$image,~third-party @@||eventcinemas.co.nz^*_adhub_server_$script @@||eventim.de/obj/basic/ad2_obj/layout/ @@||ewallpapers.eu/ads/logo.jpg @@||exoclick.com/ads.php?*login$script,domain=imgserve.net|imgtiger.com @@||expedia.co.nz/html.cms/tpid=*&adsize= @@||expedia.com/daily/common/msi.asp @@||expedia.com/html.cms/TPID=*&ADSIZE=$subdocument @@||expedia.com/js.ng/*&PLACEMENT=CXHOMECORE_$script @@||expedia.com/minify/ads-min-*.js? @@||explosm.net/comics/$image @@||explosm.net/db/files/comics/$image @@||extras.chron.com/banners/*/social_icons/$image,subdocument @@||ezone.com/banners/swfs/$object,domain=ezone.com @@||f-cdn.com/build/js/ads/main.js?$domain=freelancer.com @@||faceinhole.com/adsense.swf$object-subrequest @@||farecompare.com^*/farecomp/ @@||fbexternal-a.akamaihd.net/safe_image.php?$image,domain=facebook.com @@||feedroom.speedera.net/static.feedroom.com/affiliate/ @@||feeds.videogamer.com^*/videoad.xml?$object-subrequest @@||festina.com/txt/advertising.xml$object-subrequest @@||ff.connextra.com^$domain=pinnaclesports.com @@||fifa.com/flash/videoplayer/libs/advert_$object-subrequest @@||files.coloribus.com^$image,~third-party @@||filestage.to/design/player/player.swf?*&popunder=$object,third-party @@||fixtracking.com/images/ad-$image,~third-party @@||flashgames247.com/advertising/ima-vast-preroll.swf$object,domain=flashgames247.com @@||flipboard.com/media/uploads/adv_$image,~third-party @@||flipkart.com/affiliate/displayWidget?$subdocument,domain=affrity.com @@||flossmanuals.net/site_static/xinha/plugins/DoubleClick/$~third-party @@||flyerservices.com/cached_banner_pages/*bannerid= @@||flysaa.com^*/jquery.adserver.js @@||fmpub.net/site/$domain=theawl.com @@||fncstatic.com^*/fox411/fox-411-head-728x90.png$domain=foxnews.com @@||folklands.com/health/advertise_with_us_files/$~third-party @@||forbesimg.com/assets/js/forbes/right_rail_sticky_ad.js$domain=forbes.com @@||forex.com/adx/$image @@||fortune.com/data/chartbeat/$xmlhttprequest @@||forums.realgm.com/banners/ @@||freeads.in/classifieds/common/postad.css @@||freeads.in/freead.png @@||freeonlinegames.com/advertising/adaptv-as3.swf?$object @@||freeonlinegames.com/advertising/google-loader.swf?$object @@||freeride.co.uk/img/admarket/$~third-party @@||freeviewnz.tv^*/uploads/ads/ @@||freeworldgroup.com/googleloader/GoogleAds.swf?contentId=FWG_Game_PreLoader&$object,domain=freeworldgroup.com @@||fs-freeware.net/images/jdownloads/downloadimages/banner_ads.png @@||fsdn.com/sd/topics/advertising_64.png$domain=slashdot.org @@||funiaste.net/obrazki/*&adtype= @@||g.doubleclick.net/aclk?$subdocument,domain=nedbank.co.za @@||g.doubleclick.net/crossdomain.xml$object-subrequest,domain=~newgrounds.com @@||g.doubleclick.net/gampad/ads?$object-subrequest,domain=majorleaguegaming.com|nfl.com|player.rogersradio.ca|twitch.tv|viki.com|volarvideo.com|worldstarhiphop.com @@||g.doubleclick.net/gampad/ads?$script,domain=app.com|argusleader.com|autoguide.com|battlecreekenquirer.com|baxterbulletin.com|beqala.com|boatshop24.com|bodas.com.mx|bodas.net|bucyrustelegraphforum.com|burlingtonfreepress.com|casamentos.com.br|casamentos.pt|casamiento.com.uy|casamientos.com.ar|chillicothegazette.com|cincinnati.com|clarionledger.com|coloradoan.com|coshoctontribune.com|courier-journal.com|courierpostonline.com|dailyrecord.com|dailyworld.com|deadspin.com|defensenews.com|delawareonline.com|democratandchronicle.com|desmoinesregister.com|dnj.com|drupalcommerce.org|escapegames.com|fdlreporter.com|floridatoday.com|freep.com|games.latimes.com|gawker.com|gizmodo.com|greatfallstribune.com|greenbaypressgazette.com|greenvilleonline.com|guampdn.com|hattiesburgamerican.com|hometownlife.com|htrnews.com|indystar.com|io9.com|ithacajournal.com|jacksonsun.com|jalopnik.com|jconline.com|jezebel.com|kotaku.com|lancastereaglegazette.com|lansingstatejournal.com|lifehacker.com|livingstondaily.com|lohud.com|mansfieldnewsjournal.com|mariages.net|marionstar.com|marshfieldnewsherald.com|matrimonio.com|matrimonio.com.co|matrimonio.com.pe|matrimonios.cl|montgomeryadvertiser.com|motorcycle.com|mycentraljersey.com|mydesert.com|mysoju.com|nauticexpo.com|nedbank.co.za|nedbankgreen.co.za|newarkadvocate.com|news-leader.com|news-press.com|newsleader.com|nonags.com|orbitz.com|pal-item.com|podomatic.com|portclintonnewsherald.com|postcrescent.com|poughkeepsiejournal.com|press-citizen.com|pressconnects.com|rgj.com|sctimes.com|sheboyganpress.com|shreveporttimes.com|stargazette.com|statesmanjournal.com|stevenspointjournal.com|tallahassee.com|tennessean.com|theadvertiser.com|thedailyjournal.com|theleafchronicle.com|thenews-messenger.com|thenewsstar.com|thenorthwestern.com|thesimsresource.com|thespectrum.com|thestarpress.com|thetimesherald.com|thetowntalk.com|ticketek.com.ar|urbandictionary.com|virginaustralia.com|visaliatimesdelta.com|volokh.com|wausaudailyherald.com|weddingspot.co.uk|wisconsinrapidstribune.com|wlj.net|zanesvilletimesrecorder.com|zavvi.com|zui.com @@||g.doubleclick.net/gampad/ads?adk$domain=rte.ie @@||g.doubleclick.net/gampad/google_ads.js$domain=nedbank.co.za|nitrome.com|ticketek.com.ar @@||g.doubleclick.net/pagead/ads?ad_type=image_text^$object-subrequest,domain=ebog.com|gameark.com @@||g.doubleclick.net/pagead/ads?ad_type=text_dynamicimage_flash^$object-subrequest @@||g4tv.com/clientscriptoptimizer.ashx?*-ads.$script,stylesheet @@||gactv.com^*/javascript/ad/coread/$script @@||game.zylom.com^*.swf?*&adURL=$object @@||game.zylom.com^*/cm_loader.*.swf?$object @@||gamehouse.com/adiframe/preroll-ad/$subdocument @@||gameitnow.com/ads/gameadvertentie.php?$subdocument @@||gameitnow.com/ads/google_loader.swf$object @@||games.cnn.com/ad/$object,object-subrequest,subdocument @@||gamesgames.com/vda/friendly-iframe.html?videoPreroll300x250$subdocument @@||gan.doubleclick.net/gan_impression?lid=$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||gannett.gcion.com/addyn/$script,domain=greenbaypressgazette.com|wcsh6.com @@||garmin.com^*/Sponsors.js? @@||garrysmod.org/ads/$image,script,stylesheet @@||gcultra.com/js/exit_popup.js @@||getgamesgo.com/Banners/$image,~third-party @@||getprice.com.au/images/$domain=shopping.ninemsn.com.au|shopping.yahoo.com.au @@||gfsrv.net/ad/$domain=ogame.org|ogame.us @@||ghstatic.com/archives/*&adURL=$domain=game.zylom.com @@||girlsplay.com/banners/ima3_preloader_$object @@||gitorious.org/adv/$~third-party,xmlhttprequest @@||glamour.com/aspen/components/cn-fe-ads/js/cn.dart.js @@||glamour.com/aspen/js/dartCall.js @@||glendalenewspress.com/hive/images/adv_ @@||glnimages.s3.amazonaws.com/odw/ad$image,domain=odysseyware.com @@||globaltv.com/js/smdg_ads.js @@||gmfreeze.org/site_media//uploads/page_ad_images/$image @@||gmodules.com/ig/ifr?up_ad$domain=healthboards.com @@||gmx.com/images/outsource/application/mailclient/mailcom/resource/mailclient/flash/multiselection_upload/multiselectionupload-*.swf$object @@||go2cloud.org/aff_i?$image,domain=affrity.com @@||godlessnightsfilm.co.uk/scripts/ad-gallery/ @@||godtube.com/resource/mediaplayer/*&adzone=$object-subrequest @@||goember.com/ad/*.xml?$xmlhttprequest @@||google.*/s?*&q=$xmlhttprequest @@||google.*/search?sclient=*&q=$xmlhttprequest @@||google.*/webpagethumbnail?*&query=$script @@||google.com/_/apps-static/*/socialads/$script,stylesheet @@||google.com/_static/images/*/ads.png @@||google.com/ads/search/module/ads/*/search.js$domain=about.com|armstrongmywire.com|atlanticbb.net|bestbuy.com|bresnan.net|broadstripe.net|buckeyecablesystem.net|cableone.net|centurylink.net|charter.net|cincinnatibell.net|dish.net|ehow.com|forbbbs.org|forbes.com|hargray.net|hawaiiantel.net|hickorytech.net|homeaway.co.uk|knology.net|livestrong.com|mediacomtoday.com|midco.net|mybendbroadband.com|mybrctv.com|mycenturylink.com|myconsolidated.net|myepb.net|mygrande.net|mygvtc.com|myhughesnet.com|myritter.com|northstate.net|nwcable.net|query.nytimes.com|rentals.com|search.rr.com|searchresults.verizon.com|suddenlink.net|surewest.com|synacor.net|tds.net|toshiba.com|trustedreviews.com|truvista.net|windstream.net|windstreambusiness.net|wowway.net|zoover.co.uk|zoover.com @@||google.com/adsense/$subdocument,domain=sedo.co.uk|sedo.com|sedo.jp|sedo.kr|sedo.pl @@||google.com/adsense/search/ads.js$domain=armstrongmywire.com|atlanticbb.net|bestbuy.com|bresnan.net|broadstripe.net|buckeyecablesystem.net|cableone.net|centurylink.net|charter.net|cincinnatibell.net|dish.net|forbbbs.org|forbes.com|hargray.net|hawaiiantel.net|hickorytech.net|homeaway.co.uk|knology.net|livestrong.com|mediacomtoday.com|midco.net|mybendbroadband.com|mybrctv.com|mycenturylink.com|myconsolidated.net|myepb.net|mygrande.net|mygvtc.com|myhughesnet.com|myritter.com|northstate.net|nwcable.net|query.nytimes.com|rentals.com|search.rr.com|searchresults.verizon.com|suddenlink.net|surewest.com|synacor.net|tds.net|toshiba.com|trustedreviews.com|truvista.net|windstream.net|windstreambusiness.net|wowway.net|www.google.com|zoover.co.uk|zoover.com @@||google.com/adsense/search/async-ads.js$domain=about.com|ehow.com @@||google.com/afs/ads?$document,subdocument,domain=ehow.com|livestrong.com @@||google.com/doubleclick/studio/swiffy/$domain=www.google.com @@||google.com/search?q=$xmlhttprequest @@||google.com/uds/?file=ads&$script,domain=guardian.co.uk|landandfarm.com @@||google.com/uds/afs?$document,subdocument,domain=about.com|ehow.com|livestrong.com @@||google.com/uds/api/ads/$script,domain=guardian.co.uk @@||google.com/uds/api/ads/*/search.$script,domain=landandfarm.com|query.nytimes.com|trustedreviews.com|www.google.com @@||google.com/uds/modules/elements/newsshow/iframe.html?format=728x90^$document,subdocument @@||google.com^*/show_afs_ads.js$domain=whitepages.com @@||googleapis.com/flash/*adsapi_*.swf$domain=viki.com|wwe.com @@||googlesyndication.com/pagead/ads?$object-subrequest,domain=nx8.com @@||googlesyndication.com/simgad/$image,domain=amctheatres.com|beqala.com|bodas.com.mx|bodas.net|casamentos.com.br|casamentos.pt|casamiento.com.uy|casamientos.com.ar|drupalcommerce.org|mariages.net|matrimonio.com|matrimonio.com.co|matrimonio.com.pe|matrimonios.cl|nedbank.co.za|orbitz.com|podomatic.com|weddingspot.co.uk|wlj.net|zavvi.com @@||gopjn.com/b/$image,domain=deliverydeals.co.uk @@||gorillanation.com/storage/lightbox_code/static/companion_ads.js$domain=comingsoon.net|gamerevolution.com|sohh.com @@||gotoassist.com/images/ad/ @@||gotomeeting.com/images/ad/$image,stylesheet @@||guardian4.com/banners/$image,~third-party @@||guardianapps.co.uk^*/advertisement-features$xmlhttprequest @@||guim.co.uk^*/styles/wide/google-ads.css @@||gulflive.com/static/common/js/ads/ads.js @@||gumtree.com^*/postAd.js @@||guysen.com/script/ads.js @@||gws.ign.com/ws/search?*&google_adpage=$script @@||hafeezcentre.pk^*/ads_images/$image,~third-party @@||harmonsgrocery.com/ads/$image @@||hawaii-scuba.com/ads_styles.css @@||hbindependent.com/hive/images/adv_ @@||healthadnet.adprimemedia.com/vn/vna/data/ad.php$object-subrequest @@||healthcare.gov/global/images/widgets/him/$domain=cms.gov @@||healthline.com/resources/base/js/responsive-ads.js? @@||healthline.com/v2/ad-leaderboard-iframe?$subdocument @@||healthline.com/v2/ad-mr2-iframe?useAdsHost=*&dfpAdSite= @@||hebdenbridge.co.uk/ads/images/smallads.png @@||hellotv.in/livetv/advertisements.xml$object-subrequest @@||hentai-foundry.com/themes/default/images/buttons/add_comment_icon.png @@||hillvue.com/banners/$image,~third-party @@||hipsterhitler.com/hhcomic/wp-content/uploads/2011/10/20_advertisement.jpg @@||hipsterhitler.com/wp-content/webcomic/$image @@||historyextra.com^*_advertorial$stylesheet @@||hologfx.com/banners/$image,~third-party @@||homedepot.com^*/thdGoogleAdSense.js @@||hotnewhiphop.com/web_root/images/ads/banner-*.png @@||housebeautiful.com/ams/page-ads.js @@||housebeautiful.com/cm/shared/scripts/refreshads-*.js @@||houstonpress.com/adindex/$xmlhttprequest @@||howcast.com/flash/assets/ads/liverail.swf @@||hp.com^*/scripts/ads/$~third-party @@||huffingtonpost.co.uk/_uac/adpage.html @@||huffingtonpost.com/_uac/adpage.html @@||huffingtonpost.com/images/ads/$~third-party @@||huffpost.com/images/ads/$domain=huffingtonpost.com @@||hulkshare.com/js/adsmanager.js @@||hulu.com/published/*.flv @@||hulu.com/published/*.mp4 @@||humana-medicare.com/ad/$~document,domain=humana-medicare.com @@||huntington.com/Script/AdManager.js @@||i.cdn.turner.com^*/adserviceadapter.swf @@||i.com.com^*/adfunctionsd-*.js$domain=cbsnews.com|cbssports.com|cnettv.cnet.com|metacritic.com|tv.com|twitch.tv @@||i.espn.co.uk/ads/gamemodule_$object @@||ibnlive.com/videoads/*_ads_*.xml$object-subrequest @@||ibsrv.net/ads/$domain=carsdirect.com @@||icefilms.info/jquery.lazyload-ad-*-min.js @@||icons.iconarchive.com/icons/$image @@||identity-us.com/ads/ads.html @@||ifeelgoood.com/tapcontent-*.swf?clicktag=$object @@||iframe.ivillage.com/iframe_render? @@||ign.com/js.ng/size=headermainad&site=teamxbox$script,domain=teamxbox.com @@||ikea.com^*/img/ad_ @@||ikea.com^*/img/ads/ @@||images-amazon.com/images/*/adsimages/$domain=amazon.com @@||images-amazon.com/images/G/01/traffic/s9m/images/sweeps/$image,domain=amazon.com @@||images-amazon.com^$domain=affrity.com @@||images.dashtickets.co.nz/advertising/featured/$image @@||images.forbes.com/video/ads/blank_frame.flv$object-subrequest @@||images.frys.com/art/ads/images/$image,~third-party @@||images.frys.com/art/ads/js/$script,stylesheet @@||images.nationalgeographic.com/wpf/media-live/graphic/ @@||images.nickjr.com/ads/promo/ @@||images.rewardstyle.com/img?$image,domain=glamour.com|itsjudytime.com @@||images.vantage-media.net^$domain=yahoo.net @@||imagesbn.com/resources?*/googlead.$stylesheet,domain=barnesandnoble.com @@||imasdk.googleapis.com/flash/core/3.*/adsapi.swf$object-subrequest @@||imasdk.googleapis.com/flash/sdkloader/adsapi_3.swf$object-subrequest @@||imasdk.googleapis.com/js/core/bridge*.html$subdocument,domain=blinkboxmusic.com|cbc.ca|eboundservices.com|gamejolt.com|live.geo.tv|news.sky.com|softgames.de|thestreet.com|video.foxnews.com|waywire.com @@||imasdk.googleapis.com/js/sdkloader/ima3.js$domain=blinkboxmusic.com|cbc.ca|gamejolt.com|news.sky.com|theverge.com @@||img-cdn.mediaplex.com^$image,domain=betfair.com @@||img.espngp.com/ads/$image,domain=espnf1.com @@||img.mediaplex.com^*_afl_bettingpage_$domain=afl.com.au @@||img.thedailywtf.com/images/ads/ @@||img.travidia.com^$image @@||img.weather.weatherbug.com^*/stickers/$image,stylesheet @@||imgag.com^*/adaptvadplayer.swf$domain=egreetings.com @@||imobie.com/js/anytrans-adv.js @@||impgb.tradedoubler.com/imp?type(img)$image,domain=deliverydeals.co.uk @@||imwx.com/js/adstwo/adcontroller.js$domain=weather.com @@||incredibox.fr/advertise/_liste.js @@||incredibox.fr/image/advertise/ @@||incredibox.fr/js/advertise.js @@||indiaresults.com/advertisements/submit.png @@||indiatimes.com/configspace/ads/$object,object-subrequest @@||infoworld.com/www/js/ads/gpt_includes.js @@||innovid.com/crossdomain.xml$object-subrequest,domain=~channel4.com @@||innovid.com/iroll/package/iab-vpaid-ex/$domain=cbs.com @@||innovid.com^*/VPAIDEXIRollPackage.swf$domain=cbs.com @@||inserts2online.com/*.jsp?*&adid=$subdocument @@||inserts2online.com/images/site/viewad.gif @@||inskin.vo.llnwd.net^*/api/tvcatchup-light.js$domain=tvcatchup.com @@||inskin.vo.llnwd.net^*/api/tvcatchup.js$domain=tvcatchup.com @@||inskin.vo.llnwd.net^*/preroll_$object-subrequest,domain=tvcatchup.com @@||inskinad.com/isapadserver/ads.aspx?$script,domain=tvcatchup.com @@||inskinmedia.com^*/api/brightcove3.js$domain=virginmedia.com @@||inskinmedia.com^*/js/base/api/$domain=mousebreaker.com @@||inspire.net.nz/adverts/$image @@||intellitext.co^$~third-party @@||intellitxt.com/ast/js/nbcuni/$script @@||intentmedia.net/adServer/$script,domain=travelzoo.com @@||intentmedia.net/javascripts/$script,domain=travelzoo.com @@||interadcorp.com/script/interad.$script,stylesheet @@||investors.com/Scripts/AdScript.js? @@||inviziads.com/crossdomain.xml$object-subrequest @@||ipcamhost.net/flashads/*.swf$object-subrequest,domain=canadianrockies.org @@||ipcdigital.co.uk^*/adloader.js?$domain=trustedreviews.com @@||ipcdigital.co.uk^*/adtech.js$domain=trustedreviews.com @@||island.lk/userfiles/image/danweem/island.gif @@||itv.com/itv/hserver/*/site=itv/$xmlhttprequest @@||itv.com^*.adserver.js @@||itv.com^*/flvplayer.swf?$object @@||itv.com^*/tvshows_adcall_08.js @@||itweb.co.za/banners/en-cdt*.gif @@||jivox.com/jivox/serverAPIs/getCampaignById.php?$object-subrequest,domain=ibnlive.in.com @@||jobs.wa.gov.au/images/advertimages/ @@||jobsearch.careerone.com.au^*/bannerad.asmx/ @@||jobstreet.com/_ads/ @@||johnston.grapeshot.co.uk^$domain=peterboroughtoday.co.uk @@||joyhubs.com/View/*/js/pop.js @@||js.revsci.net/gateway/gw.js?$domain=app.com|argusleader.com|aviationweek.com|battlecreekenquirer.com|baxterbulletin.com|bucyrustelegraphforum.com|burlingtonfreepress.com|centralohio.com|chillicothegazette.com|cincinnati.com|citizen-times.com|clarionledger.com|coloradoan.com|coshoctontribune.com|courier-journal.com|courierpostonline.com|dailyrecord.com|dailyworld.com|delawareonline.com|delmarvanow.com|democratandchronicle.com|desmoinesregister.com|dnj.com|fdlreporter.com|foxsmallbusinesscenter.com|freep.com|greatfallstribune.com|greenbaypressgazette.com|greenvilleonline.com|guampdn.com|hattiesburgamerican.com|hometownlife.com|honoluluadvertiser.com|htrnews.com|indystar.com|jacksonsun.com|jconline.com|lancastereaglegazette.com|lansingstatejournal.com|livingstondaily.com|lohud.com|mansfieldnewsjournal.com|marionstar.com|marshfieldnewsherald.com|montgomeryadvertiser.com|mycentraljersey.com|mydesert.com|newarkadvocate.com|news-leader.com|news-press.com|newsleader.com|pal-item.com|pnj.com|portclintonnewsherald.com|postcrescent.com|poughkeepsiejournal.com|press-citizen.com|pressconnects.com|rgj.com|sctimes.com|sheboyganpress.com|shreveporttimes.com|stargazette.com|statesmanjournal.com|stevenspointjournal.com|tallahassee.com|tennessean.com|theadvertiser.com|thecalifornian.com|thedailyjournal.com|theithacajournal.com|theleafchronicle.com|thenews-messenger.com|thenewsstar.com|thenorthwestern.com|thespectrum.com|thestarpress.com|thetimesherald.com|thetowntalk.com|visaliatimesdelta.com|wausaudailyherald.com|weather.com|wisconsinrapidstribune.com|zanesvilletimesrecorder.com @@||jsstatic.com/_ads/ @@||jtvnw.net/widgets/jtv_player.*&referer=http://talkrtv.com/ad/channel.php?$object,domain=talkrtv.com @@||justin-klein.com/banners/ @@||kaltura.com^*/doubleClickPlugin.swf$object-subrequest,domain=tmz.com @@||kamernet.nl/Adverts/$~third-party @@||karolinashumilas.com/img/adv/ @@||kcna.kp/images/ads_arrow_ @@||kcra.com^*/adpositionsizein-min.js @@||keygamesnetwork.com/adserve/request/$object-subrequest,domain=gamesforwork.com @@||kidshealth.org/licensees/licensee1/js/gam.html @@||king5.com/templates/belo_dart_iframed_ad?dartTag=LeaderTop&$subdocument @@||kingofgames.net/gads/kingofgames.swf @@||kiz10.com/template/publicidad/ficha/ads_preloadgame/ima3_preloader_$object @@||kloubert.com/wp-content/uploads/*/Advertising_$image,~third-party @@||koaa.com/videoplayer/iframe.cfm?*&hide_ads= @@||kongcdn.com/game_icons/*-300x250_$domain=kongregate.com @@||kotak.com/banners/$image @@||krispykreme.com/content/images/ads/ @@||ksl.com/resources/classifieds/graphics/ad_ @@||l.yimg.com/*/adservice/ @@||l.yimg.com/zz/combo?*/advertising.$stylesheet @@||lacanadaonline.com/hive/images/adv_ @@||lads.myspace.com/videos/msvideoplayer.swf?$object,object-subrequest @@||lanacion.com.ar/*/publicidad/ @@||larazon.es/larazon-theme/js/publicidad.js? @@||lbdevicons.brainient.com/flash/*/VPAIDWrapper.swf$object,domain=mousebreaker.com @@||lduhtrp.net/image-$domain=uscbookstore.com @@||leadback.advertising.com/adcedge/$domain=careerbuilder.com @@||lehighvalleylive.com/static/common/js/ads/ads.js @@||lelong.com.my/UserImages/Ads/$image,~third-party @@||lemon-ads.com^$~document,~third-party @@||lesacasino.com/banners/$~third-party @@||libraryjournal.com/wp-content/plugins/wp-intern-ads/$script,stylesheet @@||lightningcast.net/servlets/getplaylist?*&responsetype=asx&$object @@||lijit.com///www/delivery/fpi.js?*&width=728&height=90$script,domain=hypeseek.com @@||limecellular.com/resources/images/adv/$~third-party @@||linkbucks.com/tmpl/mint/css/ads.css @@||linkbucks.com/tmpl/mint/img/int_skip_ad.gif @@||linkbucks.com/tmpl/mint/img/int_skip_ad_disabled.gif @@||linkconnector.com/traffic_record.php?lc=$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||linksave.in/img/usercp/ads.png @@||linkshare.iregdev.com/images/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||linksynergy.com/fs-bin/show?id=$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||linksynergy.com/fs/banners/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||lipsum.com/images/banners/ @@||listings.brokersweb.com/JsonSearchSb.aspx?*&maxAds=$script @@||live-support.se^*/Admax/$~third-party @@||live.seenreport.com:82/media/js/ads_controller.js?$domain=live.geo.tv @@||live.seenreport.com:82/media/js/fingerprint.js?$domain=live.geo.tv @@||live365.com/mini/blank300x250.html @@||live365.com/scripts/liveads.js @@||live365.com/web/components/ads/*.html? @@||liverail.com/js/LiveRail.AdManager$script,domain=~bluray-disc.de @@||liverail.com/js/LiveRail.Interstitial-$script,domain=keygames.com @@||liverail.com^*/liverail_preroll.swf$object,domain=newgrounds.com @@||liverail.com^*/vpaid-player.swf?$object,domain=addictinggames.com|keygames.com|nglmedia.com|shockwave.com @@||llnwd.net^*/js/3rdparty/swfobject$script @@||logmein.com/Serve.aspx?ZoneID=$script,~third-party @@||longtailvideo.com/flowplayer/ova-*.swf$domain=rosemaryconley.tv @@||longtailvideo.com^*/gapro.js$domain=physorg.com @@||loot.com/content/css/combo/advert_$domain=loot.com @@||lovefilm.com/ajax/widgets/advertising/$xmlhttprequest @@||lovefilm.com/static/scripts/advertising/dart.overlay.js @@||lovemybubbles.com/images/ads/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||ltassrv.com/crossdomain.xml$object-subrequest @@||ltassrv.com/yume.swf$domain=animecrazy.net|gamedorm.org|gamepro.com|satsukai.com|sparknotes.com @@||ltassrv.com/yume/yume_$object-subrequest,domain=animecrazy.net|gamedorm.org|gamepro.com|satsukai.com|sparknotes.com @@||luceosolutions.com/recruit/advert_details.php?id=$subdocument @@||lycos.com/catman/init.js$domain=video.lycos.com @@||lyngsat-logo.com/icon/flag/az/ad.gif @@||mac-sports.com/ads2/508128.swf @@||mads.cbs.com/mac-ad?$object-subrequest @@||mads.com.com/ads/common/faith/*.xml$object-subrequest @@||mads.tv.com/mac-ad?META^$script,domain=tv.com @@||magicbricks.com/img/adbanner/ @@||mail.google.com^*&view=ad&$xmlhttprequest @@||mail.google.com^*/uploaderapi*.swf @@||mail.yahoo.com/neo/assets/swf/uploader.swf @@||manilatimes.net/images/banners/logo-mt.png @@||manoramaonline.com/advt/cricbuzz/ @@||mansioncasino.com/banners/$~third-party @@||maps-static.chitika.net^ @@||maps.chitika.net^ @@||maps.gstatic.com/maps-api-*/adsense.js$domain=ctrlq.org|googlesightseeing.com|marinetraffic.com|satellite-calculations.com|walkscore.com @@||marca.com/deporte/css/*/publicidad.css @@||marciglesias.com/publicidad/ @@||marcokrenn.com/public/images/pages/advertising/$~third-party @@||marcs.com^*/AdViewer.js @@||marieclaire.com/ams/page-ads.js? @@||marines.com/videos/commercials/$object-subrequest @@||marketing.beatport.com.s3.amazonaws.com/html/*/Banner_Ads/header_$image @@||masslive.com/static/common/js/ads/ads.js @@||maxim.com/advert*/countdown/$script,stylesheet @@||mcfc.co.uk/js/core/adtracking.js @@||mcpn.us/resources/images/adv/$~third-party @@||media-azeroth.cursecdn.com/Assets/*/DOODADS/$object-subrequest @@||media-imdb.com^*/js/ads.js$domain=imdb.com @@||media.avclub.com/onion/js/videoads.js$script @@||media.cargocollective.com^$image @@||media.expedia.com/*/ads/ @@||media.glnsrv.com/ads/$image,domain=aopschools.com @@||media.monster.com/ads/$image,domain=monster.com @@||media.newjobs.com/ads/$image,object,domain=monster.com @@||media.salemwebnetwork.com/js/admanager/swfobject.js$domain=christianity.com @@||media.styleblueprint.com/ad.php?$script,~third-party @@||media.washingtonpost.com/wp-srv/ad/ad_v2.js @@||media.washingtonpost.com/wp-srv/ad/photo-ad-config.jsonp @@||media.washingtonpost.com/wp-srv/ad/tiffany_manager.js @@||mediabistro.com^*/displayadleader.asp?$subdocument @@||mediaplex.com/ad/$domain=betfair.com @@||medrx.sensis.com.au/images/sensis/*/util.js$domain=afl.com.au|goal.com @@||medrx.sensis.com.au/images/sensis/generic.js$domain=afl.com.au @@||medscape.com/html.ng/*slideshow @@||medscapestatic.com/pi/scripts/ads/dfp/profads2.js @@||memecdn.com/advertising_$image,domain=memecenter.com @@||meritline.com/banners/$image,~third-party @@||merkatia.com/adimages/$image @@||metacafe.com/banner.php? @@||metalmusicradio.com^*/banner.php @@||meviodisplayads.com/adholder.php$domain=mevio.com @@||mfcreative.com/lib/tgn/combo.ashx?$script,stylesheet,domain=ancestry.com|ancestry.com.au @@||militaryfleamarket.net/media/com_jomclassifieds/adverts/ @@||miller-mccune.com/wp-content/plugins/*/oiopub-direct/images/style/output.css @@||miniclip.com/scripts/js.php? @@||miniclipcdn.com/content/push-ads/ @@||mircscripts.org/advertisements.js @@||mlb.com/bundle?js=*/adproxy.$script,domain=mlb.com @@||mlb.com/scripts/dc_ads.js @@||mlb.com/shared/components/gameday/v6/js/adproxy.js @@||mlive.com/static/common/js/ads/ads.js @@||mns.com/ad/$domain=classifieds.nydailynews.com @@||mobilefish.com/scripts/advertisement.js @@||mochiads.com/ctr/*.swf?$domain=gamesforwork.com @@||mochiads.com/srv/*.swf?cachebust=$domain=gamesforwork.com @@||mochiads.com/srv/*.swf?cxnid=$domain=gamesforwork.com @@||mochiads.com/static/pub/swf/leaderboard.js$domain=mochigames.com @@||mofunzone.com/ads/ima3_preloader_*.swf$object @@||moneybookers.com/ads/$~third-party @@||monster.com/awm/*/ADVERTISING- @@||monster.com/services/bannerad.asmx/getadsrc$xmlhttprequest,domain=monster.com @@||movoto.com/LeaderboardAd.aspx?adSpotName=$subdocument @@||mp32u.net/adframe.js @@||msads.net/adbar/products/*/adbar.js$domain=mail.live.com @@||msi.com/js/topad/topad.css @@||msi.com/pic/banner/ @@||msnbcmedia.msn.com^*/sitemanagement/ads/*/blog_printbutton.png @@||mstar.com/ads/$image,domain=morningstar.com @@||msy.com.au/images/ADbanner/eletter/$~third-party @@||muchmusic.com/includes/js/adzone.js @@||mudah.my/css/mudah_adview_min.css @@||music-clips.net/ads/list.txt?_=$xmlhttprequest @@||music-tags.com/tagengine/www/delivery/fl.js$domain=blastro.com @@||music-tags.com/tagengine/www/delivery/spcjs.php$domain=blastro.com @@||mussil.com/mussilcomfiles/commercials/*.jpg @@||mutualofomaha.com/images/ads/ @@||mvapublicstorage.microsoft.com/banners/$domain=microsoftvirtualacademy.com @@||mxtabs.net/ads/interstitial$subdocument @@||myadt.com/js-ext/smartbanner/ @@||mycricket.com/openx/offers/$image @@||myhouseabroad.com/*/ads/ @@||myhouseabroad.com/js/adview.js @@||myprotein.com/Files/OpenX/$image,~third-party @@||myrecipes.com/static/advertising/ @@||mythings.com/c.aspx?atok$domain=enter.ru @@||napaonline.com/Content/script/jquery.lazyload-ad-$script @@||nationalbusinessfurniture.com/product/advertising/$image @@||nationalgeographic.com/channel/videos/satellite/*.swf?adsite= @@||nationmultimedia.com/new/js/doubleclick.js @@||nature.com/advertising/$~third-party @@||nba.com/mobilevideo?*&ad_url=$script,domain=mavs.wpengine.netdna-cdn.com @@||nbc.com/collarity/ @@||ncregister.com/images/ads/ @@||ncregister.com/images/sized/images/ads/ @@||nedbank.co.za/website/content/home/google_ad_Cut.jpg @@||neobux.com/v/?a=l&l=$document @@||netupd8.com/webupd8/*/adsense.js$domain=webupd8.org @@||netupd8.com/webupd8/*/advertisement.js$domain=webupd8.org @@||networkworld.com/www/js/ads/gpt_includes.js? @@||newgrounds.com/ads/ad_medals.gif @@||news.nate.com/etc/adrectanglebanner? @@||newsarama.com/common/js/advertisements.js @@||newsweek.com/ads/adscripts/prod/*_$script @@||newyorker.com/wp-content/assets/js/vendors/cn-fe-ads/cn.dart.js @@||newzimbabwe.com/banners/350x350/ @@||nextag.com/buyer/dyad/$script,domain=nextag.com @@||nextmedia.com/admedia/$object-subrequest @@||nextmovie.com/plugins/mtvnimageresizer/actions/scale_image?$image,domain=nextmovie.com @@||nfl.com^*/ads.js @@||nflcdn.com/static/*/global/ads.js @@||nflcdn.com^*/adplayer.js$domain=nfl.com @@||nflcdn.com^*/scripts/global/ads.js$domain=nfl.com @@||ngads.com/getad.php?url=$object-subrequest,domain=newgrounds.com @@||nick.com/js/ads.jsp @@||nick.com/js/coda/nick/adrefresh.js$domain=nick.com @@||nickjr.com/assets/ad-entry/ @@||nickjr.com/global/scripts/overture/sponsored_links_lib.js @@||nintandbox.net/images/*-Advertising_$image @@||nj.com/static/common/js/ads/ads.js @@||nola.com/static/common/js/ads/ads.js @@||nonstoppartner.net/a/$image,domain=deliverydeals.co.uk @@||nsandi.com/files/asset/banner-ads/ @@||nyctourist.com/www/delivery/spcjs.php?$script,domain=nyctourist.com @@||nyt.com^*/ad-loader.js$domain=nytimes.com @@||nyt.com^*/ad-view-manager.js$domain=nytimes.com @@||nytimes.com/ads/interstitial/skip*.gif @@||nytimes.com/adx/bin/adx_remote.html?type=fastscript$script,xmlhttprequest,domain=nytimes.com @@||nytimes.com/adx/images/ADS$domain=myaccount.nytimes.com @@||nytimes.com/adx/images/ads/*_buynow_btn_53x18.gif @@||nytimes.com/adx/images/ads/*_premium-crosswords_bg_600x329.gif @@||nytimes.perfectmarket.com^$stylesheet @@||oas.absoluteradio.co.uk/realmedia/ads/$object-subrequest @@||oas.absoluteradio.co.uk^*/www.absoluteradio.co.uk/player/ @@||oas.bigflix.com/realmedia/ads/$object-subrequest,domain=~tamilflix.net @@||oas.theguardian.com^$xmlhttprequest @@||oascentral.discovery.com/realmedia/ads/adstream_mjx.ads/$script,domain=discovery.com @@||oascentral.feedroom.com/realmedia/ads/adstream_sx.ads/$script,domain=businessweek.com|economist.com|feedroom.com|stanford.edu @@||oascentral.feedroom.com/realmedia/ads/adstream_sx.ads/brighthouse.com/$document,domain=oascentral.feedroom.com @@||oascentral.ibtimes.com/crossdomain.xml$object-subrequest @@||oascentral.post-gazette.com/realmedia/ads/$object-subrequest @@||oascentral.sumworld.com/crossdomain.xml$object-subrequest @@||oascentral.sumworld.com/realmedia/ads/adstream_sx.ads/*video$domain=mlssoccer.com @@||oascentral.sumworld.com/realmedia/ads/adstream_sx.ads/mlssoccer.com/$object-subrequest,domain=mlssoccer.com @@||oascentral.surfline.com/crossdomain.xml$object-subrequest @@||oascentral.surfline.com/realmedia/ads/adstream_sx.ads/www.surfline.com/articles$object-subrequest @@||oascentral.thechronicleherald.ca/realmedia/ads/adstream_mjx.ads$script @@||oascentral.thepostgame.com/om/$script @@||objects.tremormedia.com/embed/js/$domain=animecrave.com|bostonherald.com|deluxemusic.tv|deluxetelevision.com|theunlockr.com|videopoker.com|weeklyworldnews.com @@||objects.tremormedia.com/embed/sjs/$domain=nfl.com @@||objects.tremormedia.com/embed/swf/acudeoplayer.swf$domain=animecrave.com|bostonherald.com|deluxemusic.tv|deluxetelevision.com|theunlockr.com|videopoker.com|weeklyworldnews.com @@||objects.tremormedia.com/embed/swf/admanager*.swf @@||ocp.com.com/adfunctions.js? @@||offerpalads.com^*/opmbanner.js$domain=farmville.com @@||okta.com/js/app/sso/interstitial.js$~third-party @@||oldergames.com/adlib/ @@||omgili.com/ads.search? @@||omgubuntu.co.uk^*/banner.js @@||omnikool.discovery.com/realmedia/ads/adstream_mjx.ads/dsc.discovery.com/$script @@||onetravel.com/desktopmodules/adsales/adsaleshandle.ashx?$xmlhttprequest @@||onionstatic.com^*/videoads.js @@||openx.ideastudios.ro^$script,domain=enjoydressup.com @@||openx.infrontams.tv/www/$image,object,script,domain=acmilan.com @@||openx.nobelprize.org/openx/www/delivery/$script @@||openx.org/afr.php?$subdocument,domain=cubeecraft.com @@||openx.org/avw.php?zoneid$image,domain=podomatic.com @@||openx.org/ck.php?$subdocument,domain=cubeecraft.com @@||optimatic.com/iframe.html$subdocument,domain=pch.com @@||optimatic.com/integral/wrapper/shell.swf$domain=pch.com @@||optimatic.com/shell.js$domain=pch.com @@||optimatic.com^*/wrapper/shell.swf?$object,domain=pch.com @@||optimatic.com^*/wrapper/shell_standalone.swf?$object,domain=pch.com @@||oregonlive.com/static/common/js/ads/ads.js @@||osdir.com/ml/dateindex*&num=$subdocument @@||otakumode.com/shop/titleArea?*_promo_id=$xmlhttprequest @@||otrkeyfinder.com/otr/frame*.php?ads=*&search=$subdocument,domain=onlinetvrecorder.com @@||overture.london^$~third-party @@||ox-d.motogp.com/v/1.0/av?*auid=$object-subrequest,domain=motogp.com @@||ox-d.qz.com/w/1.0/jstag|$script,domain=qz.com @@||ox-d.rantsports.com/w/1.0/jstag$script,domain=rantlifestyle.com @@||ox-d.sbnation.com/w/1.0/jstag| @@||ox.eurogamer.net/oa/delivery/ajs.php?$script,domain=vg247.com @@||ox.popcap.com/delivery/afr.php?&zoneid=$subdocument,~third-party @@||oxfordlearnersdictionaries.com/external/scripts/doubleclick.js @@||ozspeedtest.com/js/pop.js @@||pachanyc.com/_images/advertise_submit.gif @@||pachoumis.com/advertising-$~third-party @@||pacogames.com/ad/ima3_preloader_$object @@||pagead2.googlesyndication.com/pagead/gadgets/overlay/overlaytemplate.swf$object-subrequest,domain=bn0.com|ebog.com|gameark.com @@||pagead2.googlesyndication.com/pagead/googlevideoadslibrary.swf$object-subrequest,domain=flashgames247.com|freeonlinegames.com|gameitnow.com|play181.com|toongames.com @@||pagead2.googlesyndication.com/pagead/imgad?$image,domain=kingofgames.net|nedbank.co.za|nedbankgreen.co.za|virginaustralia.com @@||pagead2.googlesyndication.com/pagead/imgad?id=$object-subrequest,domain=bn0.com|ebog.com|gameark.com|yepi.com @@||pagead2.googlesyndication.com/pagead/js/*/show_ads_impl.js$domain=oldapps.com @@||pagead2.googlesyndication.com/pagead/scache/googlevideoads.swf$object-subrequest,domain=flashgames247.com|freeonlinegames.com|gameitnow.com|play181.com|toongames.com @@||pagead2.googlesyndication.com/pagead/scache/googlevideoadslibraryas3.swf$object-subrequest,domain=didigames.com|nitrome.com|nx8.com|oyunlar1.com @@||pagead2.googlesyndication.com/pagead/scache/googlevideoadslibrarylocalconnection.swf?$object-subrequest,domain=didigames.com|nitrome.com|nx8.com|oyunlar1.com @@||pagead2.googlesyndication.com/pagead/show_ads.js$domain=oldapps.com @@||pagead2.googlesyndication.com/pagead/static?format=in_video_ads&$elemhide,subdocument @@||pagesinventory.com/_data/flags/ad.gif @@||pandasecurity.com/banners/$image,~third-party @@||pantherssl.com/banners/ @@||partner.googleadservices.com/gampad/google_ads.js$domain=autoguide.com|avclub.com|boatshop24.com|cadenasuper.com|dailygames.com|demotywatory.pl|drivearabia.com|ensonhaber.com|juegosdiarios.com|lbox.me|letio.com|lightinthebox.com|memegenerator.net|mysoju.com|nedbank.co.za|nedbankgreen.co.za|nitrome.com|nx8.com|playedonline.com|sulekha.com|volokh.com|yfrog.com @@||partner.googleadservices.com/gampad/google_ads2.js$domain=motorcycle.com|mysoju.com|nedbank.co.za @@||partner.googleadservices.com/gampad/google_ads_gpt.js$domain=amctheatres.com|pitchfork.com|podomatic.com|virginaustralia.com @@||partner.googleadservices.com/gampad/google_service.js$domain=autoguide.com|avclub.com|boatshop24.com|cadenasuper.com|dailygames.com|demotywatory.pl|drivearabia.com|ensonhaber.com|escapegames.com|juegosdiarios.com|lbox.me|letio.com|lightinthebox.com|memegenerator.net|motorcycle.com|mysoju.com|nedbank.co.za|nedbankgreen.co.za|nx8.com|playedonline.com|playstationlifestyle.net|readersdigest.com.au|sulekha.com|ticketek.com.ar|volokh.com|yfrog.com @@||partner.googleadservices.com/gpt/pubads_impl_$script,domain=beqala.com|bodas.com.mx|bodas.net|casamentos.com.br|casamentos.pt|casamiento.com.uy|casamientos.com.ar|deadspin.com|drupalcommerce.org|ew.com|gawker.com|gizmodo.com|io9.com|jalopnik.com|jezebel.com|kotaku.com|latimes.com|lifehacker.com|mariages.net|matrimonio.com|matrimonio.com.co|matrimonio.com.pe|matrimonios.cl|nauticexpo.com|orbitz.com|thesimsresource.com|urbandictionary.com|weddingspot.co.uk|wlj.net|zavvi.com @@||partners.thefilter.com/crossdomain.xml$object-subrequest @@||partners.thefilter.com/dailymotionservice/$image,object-subrequest,script,domain=dailymotion.com @@||paulfredrick.com/csimages/affiliate/banners/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||payload*.cargocollective.com^$image @@||pbs.org^*/sponsors/flvvideoplayer.swf @@||pch.com/templates/*/videoad.css$stylesheet @@||pennlive.com/static/common/js/ads/ads.js @@||perbang.dk/_pub/ads.php?u=$xmlhttprequest @@||perbang.dk/_pub/advertisement.js? @@||perezhilton.com/included_ads/ @@||perezhilton.com^*-without-ads-$object,object-subrequest,subdocument @@||petapixel.com/ads/$~third-party @@||petcarerx.com/banners/ @@||petra-fischer.com/tl_files/pics/*/ADVERTISING/$~third-party @@||pets4homes.co.uk/*/advert.js @@||pets4homes.co.uk^*/advert.css @@||pgatour.com/etc/designs/pgatour-advertisements/clientlibs/ad.min.js$script @@||phl.org/Advertising/$image,~third-party @@||phoenix.untd.com/OASX/$script,domain=netzero.net @@||photo.ekathimerini.com/ads/extra/$image,~third-party @@||photobucket.com/albums/ad$image @@||photobucket.com/pbkt/hserver/$object-subrequest,domain=photobucket.com @@||picmonkey.com/facebook-canvas/?ads$domain=apps.facebook.com @@||picplzthumbs.com/upload/img/ad/ @@||piercesnorthsidemarket.com/ads/$image @@||ping.indieclicktv.com/www/delivery/ajs.php?zoneid$object-subrequest @@||pinkbike.org^*.swf?ad=0&$object @@||pioneerfcu.org/assets/images/bannerads/pfcu-system-upgrade-banner-02-180x218.gif @@||pitchfork.com/desktop/js/pitchfork/ads/interstitial.js @@||planetaxel.com^*.php?ad=$stylesheet @@||planetoddity.com/wp-content/*-ads-$image @@||planetrecruit.com/ad/$image @@||player.animelicio.us/adimages/$subdocument @@||player.cdn.targetspot.com/crossdomain.xml$object-subrequest,domain=slacker.com @@||player.cdn.targetspot.com/player/ts_as3.swf?$object-subrequest,domain=slacker.com @@||player.cdn.targetspot.com/station/*/ts_config.xml$object-subrequest,domain=slacker.com @@||player.cdn.targetspot.com/ts_embed_functions_as3.php$domain=tritonmedia.com @@||player.goviral-content.com/crossdomain.xml$object-subrequest @@||player.onescreen.net/*/MediaPlayer.swf?ads=$object-subrequest @@||player.streamtheworld.com/liveplayer.php?*adstype= @@||player.tritondigital.com^$domain=kmozart.com @@||player.ventunotech.com/VtnGoogleVpaidIMA_1.swf?$object-subrequest,domain=indianexpress.com|thehindu.com @@||player.vioapi.com/ads/flash/vioplayer.swf @@||playintraffik.com/advertising/ @@||plugcomputer.org^*/ad1.jpg @@||pntrs.com^$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||politico.com/js/magazine/ads.js @@||pollen.vc/views/ads.html$domain=pollen.vc @@||pop.advecs.com^$~third-party @@||popad.co^$~third-party @@||popcap.com/sites/all/modules/popcap/js/popcap_openx.js? @@||popularmechanics.com/ams/page-ads.js$domain=popularmechanics.com @@||popunder.ru/banners/$domain=magesy.be @@||powercolor.com/image/ad/$~third-party @@||pressdisplay.com/advertising/showimage.aspx? @@||prism.opticsinfobase.org/Scripts/ADS/Details.js @@||procato.com/_pub/ads.php?u=$xmlhttprequest @@||procato.com/_pub/advertisement.js @@||productioncars.com/pics/menu/ads.gif @@||productioncars.com/pics/menu/ads2.gif @@||promo.acronis.com^*?base=www.acronis.$subdocument @@||promo.campaigndog.com^$third-party @@||promo2.tubemogul.com/adtags/slim_no_iframe.js$domain=comedy.com @@||promo2.tubemogul.com/flash/youtube.swf$domain=comedy.com @@||promo2.tubemogul.com/lib/tubemoguldisplaylib.js$domain=comedy.com @@||promophot.com/photo/ad/$image @@||proprofs.com/quiz-school/js/modernizr_ads.js @@||proxyserver.asia/themes/advertising-$image,stylesheet @@||pshared.5min.com/Scripts/ThumbSeed2.js?*&adUnit=$script @@||ptgrey.com/_PGR_Content/Advertising/$image,~third-party @@||pubmatic.com/AdServer/js/universalpixel.js$domain=politico.com @@||pubmatic.com/AdServer/UPug?$script,domain=politico.com @@||pumpkinpatchkids.com/www/delivery/ajs.php?$script @@||pursuit.co.za/css/globalAd.css @@||puzzler.com/commercials/*.htm$subdocument @@||q2servers.com/pop.js @@||qnsr.com/cgi/r?$domain=insure.com @@||query.vap.yahoo.net/nicobarMan/ads/acctid=$object-subrequest,domain=yahoo.com @@||quit.org.au/images/images/ad/ @@||qzprod.files.wordpress.com^*?w=$domain=qz.com @@||r2games.com/bannerad/$image,~third-party @@||rackcdn.com/banners/$image,domain=rackspace.co.uk|rackspace.com.au @@||rackcdn.com/banners/default_coupon_banner.png$domain=michaels.com @@||rad.msn.com/ADSAdClient31.dll?GetAd=$xmlhttprequest,domain=ninemsn.com.au @@||rad.org.uk/images/adverts/$image,~third-party @@||radioguide.fm/minify/?*/Advertising/webroot/css/advertising.css @@||radiotimes.com/rt-service/resource/jspack? @@||rainbowdressup.com/ads/adsnewvars.swf @@||rapoo.com/images/ad/$image,~third-party @@||rc.hotkeys.com/interface/$domain=ehow.com @@||rcards.net/wp-content/plugins/useful-banner-manager/ @@||rcards.net/wp-content/uploads/useful_banner_manager_banners/ @@||rcm-images.amazon.com/images/$domain=rankbank.net @@||rcm.amazon.com/e/cm$domain=asianmommy.com|filmcrave.com @@||readwrite.com/files/styles/$image @@||realbeauty.com/ams/page-ads.js? @@||realmedia.channel4.com/realmedia/ads/adstream_sx.ads/channel4.newcu/$object-subrequest,~third-party @@||realvnc.com/assets/img/ad-bg.jpg @@||redbookmag.com/ams/page-ads.js? @@||redsharknews.com/components/com_adagency/includes/$script @@||refline.ch^*/advertisement.css @@||remo-xp.com/wp-content/themes/adsense-boqpod/style.css @@||replgroup.com/banners/$image,~third-party @@||req.tidaltv.com^$object-subrequest,domain=daisuki.net @@||revealads.appspot.com/revealads2/radioplayer.js$domain=talksport.co.uk @@||revit.eu/static/uploads/images/themes/banners/small-banner-$object-subrequest @@||revresda.com/event.ng/Type=click&$subdocument,domain=cheaptickets.com|orbitz.com @@||revresda.com/js.ng/*&adsize=544x275&$script,domain=cheaptickets.com @@||revresda.com/js.ng/*&adsize=960x400&$script,domain=orbitz.com @@||rewaz.org/ads/adframe2.js @@||rmncdn.com/ads/mini-$image @@||rogersdigitalmedia.com^*/rdm-ad-util.min.js$domain=citytv.com @@||rogersmagazines.com/ads/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||rosauers.com/locations/ads.html @@||rotate.infowars.com/www/delivery/fl.js @@||rotate.infowars.com/www/delivery/spcjs.php @@||rottentomatoescdn.com^*/SocialAds.js$domain=rottentomatoes.com @@||rover.ebay.com^*&size=120x60&$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||rovicorp.com/advertising/*&appver=$xmlhttprequest,domain=charter.net @@||rsvlts.com/wp-content/uploads/*-advertisment- @@||rt.liftdna.com/forbes_welcome.js$domain=forbes.com @@||rt.liftdna.com/fs.js$domain=formspring.me @@||rt.liftdna.com/liftrtb2_2.js$domain=formspring.me @@||rthk.hk/assets/flash/rthk/*/ad_banner$object @@||rthk.org.hk/assets/flash/rthk/*/ad_banner$object @@||russellrooftiles.co.uk/images/rrt_envirotile_home_advert.png @@||ryuutama.com/ads/ads.php?get=$xmlhttprequest @@||s.ytimg.com/yts/swfbin/player-*/watch_as3.swf$object,domain=youtube.com @@||s0.2mdn.net^$domain=britishgas.co.uk|luxurylink.com @@||sal.co.th/ads/$image,~third-party @@||sales.liveperson.net/visitor/addons/deploy2.asp?*&d_id=adcenter&$script @@||salon.com/content/plugins/salon-ad-controller/ad-utilities.js @@||sascdn.com/crossdomain.xml$object-subrequest @@||sascdn.com^*/jwplayer-plugin.swf?$object-subrequest @@||sascdn.com^*/jwplayerAdPlugin.swf$object-subrequest @@||save.ca/img/ads/$~third-party @@||scanscout.com/ads/$object-subrequest,domain=livestream.com @@||scanscout.com/crossdomain.xml$object-subrequest @@||scity.tv/js/ads.js$domain=live.scity.tv @@||screenwavemedia.com/play/SWMAdPlayer/SWMAdPlayer.html?type=ADREQUEST&$xmlhttprequest,domain=cinemassacre.com @@||scribdassets.com/aggregated/javascript/ads.js?$domain=scribd.com @@||scrippsnetworks.com/common/adimages/networkads/video_ad_vendor_list/approved_vendors.xml$object-subrequest @@||scutt.eu/ads/$~third-party @@||sdcdn.com/cms/ads/piczo/$image @@||sdelkino.com/images/ad/$image @@||sdltutorials.com/Data/Ads/AppStateBanner.jpg @@||search.comcast.net/static.php?$stylesheet @@||sec-ads.bridgetrack.com/ads_img/ @@||secondlife.com/assets/*_AD3.jpg @@||securenetsystems.net/advertising/ad_campaign_get.cfm?$xmlhttprequest @@||securenetsystems.net/scripts/*/sdfy_scripts_advertising.js @@||sedo.com/ox/www/delivery/ajs.php$domain=sedo.com|sedo.de @@||sekonda.co.uk/advert_images/ @@||selsin.net/imprint-$image @@||serve.vdopia.com/crossdomain.xml$object-subrequest @@||serve.vdopia.com/js/vdo.js$domain=indiatvnews.com|intoday.in @@||servebom.com/tmnhead.js$domain=tomsguide.com|tomshardware.com @@||server.cpmstar.com/adviewas3.swf?contentspotid=$object-subrequest @@||server.cpmstar.com/view.aspx?poolid=$domain=manga2u.co|newgrounds.com|xfire.com @@||serviceexpress.net/js/pop.js @@||serving-sys.com/SemiCachedScripts/$domain=cricketwireless.com @@||seventeen.com/ams/page-ads.js @@||sfdict.com/app/*/js/ghostwriter_adcall.js$domain=dynamo.dictionary.com @@||sh.st/bundles/smeadvertisement/img/track.gif?$xmlhttprequest @@||shacknews.com/advertising/preroll/$domain=gamefly.com @@||shackvideo.com/playlist_xml.x? @@||share.pingdom.com/banners/$image @@||shareasale.com/image/$domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||sharinspireds.co.nf/Images/Ads/$~third-party @@||shawfloors.com/adx/$image,~third-party @@||shelleytheatre.co.uk/filmimages/banners/160 @@||shopmanhattanite.com/affiliatebanners/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||siamautologistics.com/ads/$image,~third-party @@||sify.com/news/postcomments.php?*468x60.html @@||signin.verizon.com^*/affiliate/$subdocument,xmlhttprequest @@||sihanoukvilleonline.com/banners/sologo.png @@||silive.com/static/common/js/ads/ads.js @@||sillyvamp.com/ads/Donate.png @@||site-jump.com/banners/ @@||sjsuspartans.com/ads2/$image @@||skymediator.com/ads/*/skymediator.php?$subdocument @@||skypeassets.com^*/advertise/$domain=skype.com @@||slotsheaven.com/banners/$~third-party @@||slowblog.com/ad.js @@||smartadserver.com/call/pubj/*/8596/s/*/?$script,domain=cuantarazon.com|cuantocabron.com|vistoenfb.com @@||smartclip.net/delivery/tag?$object-subrequest,domain=nfl.com @@||smc.temple.edu/advertising/$domain=smctemple.wpengine.com @@||smctemple.wpengine.com/advertising/$~third-party @@||smileonthetiles2.co.uk/openx/www/$image,script,subdocument,domain=smileonthetiles.com|smileonthetiles2.co.uk @@||smmirror.com^*/getads.php @@||socialblogsitewebdesign.com^*/advertising_conversion_images/ @@||softwarepromotions.com/adwords/$~third-party @@||softwarepromotions.com/images/google-adwords-professional.gif @@||somethingsexyplanet.com/image/adzones/ @@||somewheresouth.net/banner/banner.php$image @@||songza.com/advertising/top/ @@||songza.com/static/*/songza/ads/iframe.js @@||sonicstate.com/video/hd/hdconfig-geo.cfm?$object-subrequest @@||sonypictures.com/global/images/ads/300x250/ad300x250.json$xmlhttprequest @@||sonypictures.com^*/admedia/ @@||southwest.com/assets/images/ads/ad_select_flight_ @@||southwest.com^*/homepage/ads/ @@||spectrum.ieee.org/assets/js/masonry-ads-right.min.js @@||spendino.de/admanager/ @@||sploder.com/prerollad.swf?s=$object-subrequest @@||sponsorselect.com/direct/preroll.aspx?$subdocument,domain=pch.com @@||sponsorselect.com/Direct/SponsorIndex.aspx$domain=pch.com @@||spotrails.com/crossdomain.xml$object-subrequest @@||spotrails.com^*/flowplayeradplayerplugin.swf @@||spotxchange.com/ad_player/as3.swf$domain=games.yahoo.com|onescreen.net @@||spotxchange.com/crossdomain.xml$object-subrequest @@||spotxchange.com/flash/ad.swf?$domain=directon.tv|wii-cast.tv @@||spotxchange.com/flash/adplayer.swf$domain=boxlive.tv|directon.tv|foxnews.ws|icastlive.tv|wii-cast.tv @@||spotxchange.com/media/videos/flash/ad_player/$domain=directon.tv|games.yahoo.com|onescreen.net|wii-cast.tv @@||spotxchange.com/media/videos/flash/adplayer_$domain=directon.tv @@||springboardplatform.com/storage/lightbox_code/static/companion_ads.js @@||springbokradio.com/images/ads- @@||springbokradio.com/sitebuilder/images/ads- @@||sprint.com^*/adservice/$xmlhttprequest @@||sprouts.com/ad/$image,subdocument @@||ssacdn.com/banners/$domain=supersonicads.com @@||ssl-images-amazon.com/images/G/01/traffic/s9m/images/sweeps/$image,domain=amazon.com @@||ssl-images-amazon.com^*/popover/popover-$script @@||st.com^*/banners.js @@||startxchange.com/textad.php?$xmlhttprequest @@||state.co.us/caic/pub_bc_avo.php?zone_id=$subdocument @@||statedesign.com/advertisers/$image,~third-party @@||static.adzerk.net/ados.js$domain=stackoverflow.com @@||static.ak.fbcdn.net^*/ads/$script @@||static.bored.com/advertising/top10/$image,domain=bored.com @@||stats.g.doubleclick.net/dc.js$domain=native-instruments.com|nest.com|theheldrich.com @@||stclassifieds.sg/images/ads/$~third-party @@||stclassifieds.sg/postad/ @@||stickam.com/css/ver1/asset/sharelayout2col_ad300x250.css @@||streaming.gmgradio.com/adverts/*.mp3$object-subrequest @@||streamlive.to/ads/$object,script @@||style.com/flashxml/*.doubleclick$object @@||style.com/images/*.doubleclick$object @@||subscribe.newyorker.com/ams/page-ads.js @@||subscribe.teenvogue.com/ams/page-ads.js @@||sulekhalive.com/images/property/bannerads/$domain=sulekha.com @@||summitracing.com/global/images/bannerads/ @@||supercartoons.net/ad-preroll.html @@||superfundo.org/advertisement.js @@||supersonicads.com/api/rest/funds/*/advertisers/$~third-party @@||supersonicads.com/api/v1/trackCommission.php*password=$image @@||supersonicads.com/delivery/singleBanner.php?*&bannerId$subdocument @@||support.dlink.com/Scripts/custom/pop.js @@||svcs.ebay.com/services/search/FindingService/*affiliate.tracking$domain=bkshopper.com|geo-ship.com|testfreaks.co.uk|watchmydeals.com @@||swordfox.co.nz^*/advertising/$~third-party @@||syn.5min.com/handlers/SenseHandler.ashx?*&adUnit=$script @@||syndication.streamads.yahoo.com/na_stream_brewer/brew/*?cid=*&url=*&pvid=*&callback=$script,domain=yimg.com @@||syracuse.com/static/common/js/ads/ads.js @@||tacdn.com^*_popunder_$script,stylesheet @@||tags.bkrtx.com/js/bk-coretag.js$domain=zillow.com @@||take40.com/common/javascript/ads.js @@||talkgold.com/bans/rss.png @@||talkrtv.com/ad/channel.php?$subdocument @@||tbns.com.au/shops/images/ads/$~third-party @@||tcadops.ca/consumer/adtagtc_$script,domain=metro.ca @@||tctechcrunch2011.files.wordpress.com^$image,domain=techcrunch.com @@||teamcococdn.com^*/AdManager_*.swf?$object-subrequest,domain=teamcoco.com @@||teknikor.com/content/wp-content/themes/*-adv.jpg @@||telegraphcouk.skimlinks.com/api/telegraph.skimlinks.js @@||temple.edu/advertising/$~third-party @@||tetrisfriends.com/ads/google_dfp_video_ad.html @@||texasstudentmedia.com/advertise/ @@||theatlantic.com/widget/$xmlhttprequest @@||thedailygreen.com/ams/page-ads.js? @@||thedoujin.com/includes/ads/$subdocument,domain=thedoujin.com @@||theepochtimes.com/ads/video/inarticle-video.html$subdocument @@||theepochtimes.com/ads/videos-below.htm?$subdocument @@||theepochtimes.com/ads/videos-right.html?$subdocument @@||theepochtimes.com^*/article-ads.js? @@||thefrisky.com/js/adspaces.min.js @@||thekraftgroup.com/crossdomain.xml$object-subrequest @@||theloop.com.au/js/simplejob_ad_content.js? @@||themoneyconverter.com/CurrencyConverter.aspx?*business-standard.com/ads/currency_converter_img.jpg$subdocument,domain=business-standard.com @@||thenewage.co.za/classifieds/images2/postad.gif @@||thenewsroom.com^*/advertisement.xml$object-subrequest @@||theory-test.co.uk/css/ads.css @@||theplatform.com/current/pdk/js/plugins/doubleclick.js$domain=cbc.ca @@||thestreet-static.com/video/js/companionAdFunc.js$domain=thestreet.com @@||thetvdb.com/banners/ @@||theweathernetwork.com/js/adrefresh.js @@||theweathernetwork.com/tpl/web/adtech/$xmlhttprequest @@||thomann.de/thumb/*/pics/adv/adv_image_ @@||thomsonlocal.com/js/adsense-min.js @@||thrifty.co.uk/bannerads/ @@||thumbs.hexagram.com^$domain=scribol.com @@||thunderheadeng.com/wp-content/uploads/*300x250 @@||tidaltv.com/crossdomain.xml$object-subrequest,domain=~channel4.com|~itv.com @@||timeinc.net/golf/static/ads/iframe_ad_factory.js$domain=golf.com @@||timeinc.net/people/static/i/advertising/getpeopleeverywhere-$image,domain=people.com|peoplestylewatch.com @@||timeinc.net^*/tii_ads.js @@||timeout.com/images/ads/weather/ @@||timesofmalta.com/videoads/*preroll.flv$object-subrequest @@||tinbuadserv.com/js/integrate/ads_common.js @@||tinbuadserv.com/v3/serve.php?$script @@||tinysubversions.com/clickbait/adjs.json @@||tkcarsites.com/soba/bannersservice @@||tnol.com/adimages/digitaledition/$object-subrequest @@||tntexpress.com.au^*/marketing/banners/ @@||tooltrucks.com/ads/$image,~third-party @@||tooltrucks.com/banners/$image,~third-party @@||toongames.com/advertising/toon-google-preloader.swf$object @@||topgear.com^*/ads.min.js @@||topusajobs.com/banners/ @@||toshiba.*^banner_id^$subdocument @@||track.adform.net/serving/scripts/trackpoint/$script,domain=strokekampanjen.se|tigerofsweden.com @@||trade-a-plane.com/AdBox/js/jquery.TAP_AdBox.js @@||tradecarview.com/material/housead/$image @@||tradedoubler.com/file/$image,domain=deliverydeals.co.uk @@||trader.ca/TraderMobileAPIBB.asmx/GetAds?$script,domain=autos.ca @@||traktorpool.de/scripts/advert/ @@||traktorpool.de^*/advert. @@||translate.google.*/translate_*&q=$~third-party,xmlhttprequest @@||translate.google.com/translate/static/*-ads/ @@||traumagame.com/trauma_data/ads/ad2.jpg @@||travelocity.com/event.ng/*click$domain=travelocity.com @@||travelocity.com/html.ng/*558x262$domain=travelocity.com @@||travelocity.com/js.ng/$script,domain=travelocity.com @@||travidia.com/fsi/page.aspx?$subdocument @@||travidia.com/ss-page/ @@||tremor.nuggad.net/crossdomain.xml$object-subrequest @@||tremormedia.com/acudeo/$script,domain=indiatimes.com @@||trialpay.com/js/advertiser.js @@||trifort.org/ads/$~third-party @@||trulia.com/modules/ad_agents_$xmlhttprequest @@||trustedreviews.com^*/adtech.js @@||trutv.com/includes/banners/de/video/*.ad|$object-subrequest @@||tubemogul.com/bootloader/tubemogulflowplayer.swf$object-subrequest @@||tubemogul.com/crossdomain.xml$object-subrequest @@||tudouui.com/bin/player2/*&adsourceid= @@||turner.com/adultswim/big/promos/$media,domain=video.adultswim.com @@||turner.com/xslo/cvp/ads/freewheel/bundles/2/AdManager.swf?$object-subrequest,domain=tbs.com @@||turner.com^*/ads/freewheel/*/AdManager.js$domain=cnn.com @@||turner.com^*/ads/freewheel/bundles/*/renderers.xml$object-subrequest,domain=cartoonnetwork.com|tnt.tv @@||turner.com^*/ads/freewheel/bundles/2/admanager.swf$domain=adultswim.com|cartoonnetwork.com|games.cnn.com|nba.com @@||turner.com^*/ads/freewheel/js/fwjslib_1.1.js$domain=nba.com @@||turner.com^*/videoadrenderer.swf$domain=tntdrama.com @@||tut.by/uppod/frameid406/ads1/ @@||tv-kino.net/wp-content/themes/*/advertisement.js @@||tvgorge.com^*/adplayer.swf @@||tvnz.co.nz/*/advertisement.js @@||twitvid.com/mediaplayer_*.swf? @@||twogag.com/comics/$image,~third-party @@||u.openx.net/v/1.0/sc?$object-subrequest,domain=motogp.com @@||ucaster.eu/static/scripts/adscript.js @@||uillinois.edu/eas/ @@||ukbride.co.uk/css/*/adverts.css @@||ultimate-guitar.com/js/ug_ads.js @@||ultrabrown.com/images/adheader.jpg @@||undsports.com/ads2/$image @@||upc-cablecom.ch^*.swf?clicktag=http$object @@||upload.wikimedia.org/wikipedia/ @@||uploaded.net/affiliate/$~third-party,xmlhttprequest @@||urbanog.com/banners/$image @@||usairways.com^*/doubleclick.js @@||usanetwork.com^*/usanetwork_ads.s_code.js? @@||usps.com/adserver/ @@||utarget.co.uk/crossdomain.xml$object-subrequest @@||utdallas.edu/locator/maps/$image @@||utdallas.edu/maps/images/img/$image @@||utdallas.edu^*/banner.js @@||uuuploads.com/ads-on-buildings/$image,domain=boredpanda.com @@||v.fwmrm.net/*/AdManager.swf$domain=marthastewart.com @@||v.fwmrm.net/ad/p/1?$object-subrequest,domain=abc.go.com|abcfamily.go.com|abcnews.go.com|adultswim.com|cartoonnetwork.com|cc.com|channel5.com|cmt.com|colbertnation.com|comedycentral.com|eonline.com|espn.go.com|espndeportes.com|espnfc.co.uk|espnfc.com|espnfc.com.au|espnfc.us|espnfcasia.com|gametrailers.com|ign.com|logotv.com|mlb.mlb.com|mtv.com|mtvnservices.com|nascar.com|nbc.com|nbcnews.com|nbcsports.com|nick.com|player.theplatform.com|simpsonsworld.com|sky.com|southpark.nl|southparkstudios.com|spike.com|teamcoco.com|teennick.com|thedailyshow.com|thingx.tv|tv3play.se|tvland.com|uverseonline.att.net|vevo.com|vh1.com|video.cnbc.com|vod.fxnetworks.com @@||v.fwmrm.net/crossdomain.xml$object-subrequest @@||v.fwmrm.net/p/espn_live/$object-subrequest @@||v.fwmrm.net/|$object-subrequest,domain=tv10play.se|tv3play.se|tv6play.se|tv8play.se @@||vacationstarter.com/hive/images/adv_ @@||vad.go.com/dynamicvideoad?$object-subrequest @@||vagazette.com/hive/images/adv_ @@||valueram.com/banners/ads/ @@||vancouversun.com/js/adsync/adsynclibrary.js @@||vanityfair.com/ads/js/cn.dart.bun.min.js @@||veetle.com/images/common/ads/ @@||ventunotech.akamai-http.edgesuite.net/VtnGoogleVpaid.swf?*&ad_type=$object-subrequest,domain=cricketcountry.com @@||vhobbies.com/admgr/*.aspx?ZoneID=$script,domain=vcoins.com @@||viamichelin.*/rentacar.js @@||viamichelin.*/static/advert/afsquery/afsquery.js @@||viamichelin.*/static/advert/sponsoring/itinerarypage/itinerarypage.js @@||vidcoin.com/adserver/$subdocument,xmlhttprequest @@||video.economist.com/adfinder.jsp? @@||video.nbcuni.com^*/ad_engine_extension_nbc.swf @@||video.nbcuni.com^*/inext_ad_engine/ad_engine_extension.swf @@||video.unrulymedia.com/iframe_$subdocument,domain=theemptynestexpress.com @@||video.unrulymedia.com/wildfire_$script,domain=theemptynestexpress.com @@||videoads.washingtonpost.com^$object-subrequest,domain=slatev.com @@||videosxml.mobileads.indiatimes.com^$object-subrequest @@||vidspot.net/blank.html|$subdocument @@||vidspot.net/builtin-$subdocument @@||vidspot.net/cgi-bin/upload.cgi?upload_id=*&X-Progress-ID=*&js_on=*&utype=*&upload_type=$subdocument @@||vidspot.net/tmp/status.html?*upload=file$subdocument @@||vidtech.cbsinteractive.com/plugins/*_adplugin.swf @@||villermen.com/minecraft/banner/banner.php$image @@||vindicoasset.edgesuite.net/repository/campaigncreative/*/instreamad/$object-subrequest @@||vistek.ca/ads/ @@||vitalitymall.co.za/images/adrotator/ @@||vizanime.com/ad/get_ads? @@||vk.com/ads?act=$~third-party @@||vk.com/ads_rotate.php$domain=vk.com @@||vmagazine.com/web/css/ads.css @@||vombasavers.com^*.swf?clickTAG=$object,~third-party @@||vswebapp.com^$~third-party @@||vtstage.cbsinteractive.com/plugins/*_adplugin.swf @@||w.org/adsense-plugin/assets/banner-$image,domain=wordpress.org @@||w.org/plugins/adsense-plugin/screenshot-$image,domain=wordpress.org @@||wahoha.com^$~third-party @@||wahooads.com/Ads.nsf/$~third-party @@||wallpapersmania.com/ad/$image,~third-party @@||walmartmoneycard.com^*/shared/ad_rotater.swf @@||wappalyzer.com/sites/default/files/icons/$image @@||washingtonpost.com/wp-adv/advertisers/russianow/ @@||washingtonpost.com/wp-srv/ad/generic_ad.js @@||washingtonpost.com/wp-srv/ad/textlink_driver.js @@||washingtonpost.com/wp-srv/ad/textlinks.js @@||washingtonpost.com/wp-srv/ad/textlinks_config.js @@||washingtonpost.com/wp-srv/ad/wp.js @@||washingtonpost.com/wp-srv/ad/wp_ad.js @@||washingtonpost.com/wp-srv/ad/wp_config.js @@||washingtonpost.com/wp-srv/ad/wpni_generic_ad.js @@||washingtonpost.com^*=/ad/audsci.js @@||we7.com/api/streaming/advert-info?$object-subrequest @@||wearetennis.com/pages/home/img/ad-$image @@||web-jp.ad-v.jp/adam/inline?$object-subrequest,domain=daisuki.net @@||web-jp.ad-v.jp/crossdomain.xml$domain=daisuki.net @@||wellsfargo.com/img/ads/$~third-party @@||whitepages.com^*/google_adsense.js? @@||whittakersworldwide.com/site-media/advertisements/ @@||whstatic.com/images/thumb/*-Popup-Ads-$image,domain=wikihow.com @@||widget.breakingburner.com/ad/$subdocument @@||widget.slide.com^*/ads/*/preroll.swf @@||widgets.cbslocal.com/player/embed?affiliate=$subdocument @@||widgets.rewardstyle.com^$domain=glamour.com|itsjudytime.com @@||widgetserver.com/syndication/get_widget.html?*&widget.adplacement=$subdocument @@||williamsauction.com/Resources/images/ads/$~third-party @@||wired.com^*/cn-fe-ads/cn.dart.js @@||wirefly.com/_images/ads/ @@||wisegeek.com/res/contentad/ @@||worldstarhiphop.com^*/dj2.swf @@||wortech.ac.uk/publishingimages/adverts/ @@||wp.com/_static/*/criteo.js @@||wp.com/ads-pd.universalsports.com/media/$image @@||wp.com/www.noobpreneur.com/wp-content/uploads/*-ad.jpg?resize=$domain=noobpreneur.com @@||wpthemedetector.com/ad/$~third-party @@||wrapper.teamxbox.com/a?size=headermainad @@||wsj.net^*/images/adv-$image,domain=marketwatch.com @@||www.facebook.com/ad.*^ajaxpipe^$subdocument,~third-party @@||www.google.*/aclk?*&adurl=$subdocument,~third-party @@||www.google.*/search?$subdocument @@||www.google.*/settings/u/0/ads/preferences/$~third-party,xmlhttprequest @@||www.google.com/ads/preferences/$image,script,subdocument @@||www.networkadvertising.org/choices/|$document @@||www8-hp.com^*/styles/ads/$domain=hp.com @@||yadayadayada.nl/banner/banner.php$image,domain=murf.nl|workhardclimbharder.nl @@||yahoo.com/combo?$stylesheet @@||yahoo.net/1/adnetwork/$object-subrequest @@||yceml.net^$image,domain=affrity.com|catalogfavoritesvip.com|deliverydeals.co.uk|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||yceml.net^$object,domain=affrity.com @@||yellowpages.com.mt/Images/Design/Buttons/advert.png @@||yellupload.com/yell/videoads/*.flv| @@||yellupload.com/yell/videoads/yellvideoplayer.swf? @@||yimg.com/ks/plugin/adplugin.swf?$domain=yahoo.com @@||yimg.com/p/combo?$stylesheet,domain=yahoo.com @@||yimg.com/rq/darla/*/g-r-min.js$domain=yahoo.com @@||yimg.com/zz/combo?*&*.js @@||yimg.com^*&yat/js/ads_ @@||yimg.com^*/adplugin_*.swf$object,domain=games.yahoo.com @@||yimg.com^*/ads-min.css$domain=yahoo.com @@||yimg.com^*/java/promotions/js/ad_eo_1.1.js @@||ykhandler.com/adframe.js @@||yokosonews.com/files/cache/ @@||yoox.com/img//banner/affiliation/$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@||youtube.com/yt/advertise/medias/images/$image @@||youtube.com/yt/css/www-advertise.css @@||youtube.com^*_adsense_$xmlhttprequest @@||ytimg.com/yts/img/channels/*_banner-*.jpg$domain=youtube.com @@||ytimg.com/yts/img/channels/*_banner-*.png$domain=youtube.com @@||ytimg.com^*/channels4_banner.jpg?$domain=youtube.com @@||ytimg.com^*/channels4_banner_hd.jpg?$domain=youtube.com @@||yttalk.com/threads/*/add-reply$domain=yttalk.com @@||yumenetworks.com/content/static/$domain=dailygames.com @@||yumenetworks.com/crossdomain.xml$object-subrequest @@||zamimg.com/modelviewer/*/doodads/$object-subrequest,domain=wowhead.com @@||zap2it.com/ads/newsletter/$image,~third-party @@||zattoo.com/?advideo/*;vidAS=PRE_ROLL;$object-subrequest @@||zattoo.com/advertising/channelswitch/$subdocument @@||zedo.com/bar/*/fnsr.vast?$object-subrequest,domain=ibnlive.in.com @@||zedo.com/crossdomain.xml$object-subrequest @@||zedo.com/jsc/c5/fhs.js$domain=rrstar.com @@||zedo.com/swf/$domain=startv.in @@||zeenews.india.com/ads/jw/player.swf$object @@||ziehl-abegg.com/images/img_adverts/$~third-party @@||zillow.com/ads/FlexAd.htm?did=$subdocument @@||zillow.com/widgets/search/ZillowListingsWidget.htm?*&adsize=$subdocument,domain=patch.com ! Bug #1865: ABP for Chrome messes up the page on high DPI (https://issues.adblockplus.org/ticket/1865) @@||ads.tw.adsonar.com/adserving/getAdsAPI.jsp?callback=aslHandleAds*&c=aslHandleAds*&key=$script,domain=techcrunch.com ! Anti-Adblock @@.audio/$script,domain=cbs.com @@.bmp^$image,domain=cbs.com @@.click/$script,third-party,domain=cbs.com @@.gif#$domain=9tutorials.com|aseanlegacy.net|budget101.com|cbox.ws|eventosppv.me|funniermoments.com|ibmmainframeforum.com|onlinemoviesfreee.com|premiumleecher.com|remo-xp.com|showsport-tv.com|superplatyna.com|turktorrent.cc|tv-porinternet.com.mx|ver-flv.com|xup.in @@.gif#$image,domain=360haven.com|needrom.com @@.gif?ad_banner=$domain=majorleaguegaming.com @@.gif|$object-subrequest,domain=cbs.com @@.info^$image,script,third-party,domain=cbs.com @@.javascript|$domain=cbsnews.com @@.jpeg|$object-subrequest,domain=cbs.com @@.jpg#$domain=desionlinetheater.com|firsttube.co|lag10.net|livrosdoexilado.org|mac2sell.net|masfuertequeelhierro.com|movie1k.net|play-old-pc-games.com|rtube.de|uploadlw.com @@.jpg|$object-subrequest,domain=cbs.com @@.jscript|$script,third-party,domain=cbs.com @@.link/$script,domain=cbs.com @@.min.js$domain=ftlauderdalewebcam.com|nyharborwebcam.com|portcanaveralwebcam.com|portevergladeswebcam.com|portmiamiwebcam.com @@.mobi/$script,domain=cbs.com @@.png#$domain=300mblink.com|amigosdelamili.com|android-zone.org|anime2enjoy.com|anizm.com|anonytext.tk|backin.net|better-explorer.com|bitcofree.com|chrissmoove.com|cleodesktop.com|debrastagi.com|debridit.com|debridx.com|fcportables.com|go4up.com|hackintosh.zone|hogarutil.com|hostyd.com|ilive.to|lordpyrak.net|marketmilitia.org|mastertoons.com|mediaplaybox.com|minecraft-forum.net|myksn.net|pes-patch.com|portalzuca.net|premium4.us|puromarketing.com|realidadscans.org|secureupload.eu|stream2watch.me|stream4free.eu|streamlive.to|superplatyna.com|trizone91.com|turkdown.com|url4u.org|vencko.net|wowhq.eu @@.png?*#$domain=mypapercraft.net|xlocker.net @@.png?ad_banner=$domain=majorleaguegaming.com @@.png?advertisement_$domain=majorleaguegaming.com @@.png^$image,domain=cbs.com @@.streamads.js$third-party,domain=cbs.com @@.xzn.ir/$script,third-party,domain=psarips.com @@/adFunctionsD-cbs.js$domain=cbs.com @@/adlogger_tracker.php$subdocument,domain=chrissmoove.com @@/ads/popudner/banner.jpg?$domain=spinandw.in @@/advertisement.js$domain=dramacafe.in|ilive.to @@/advertisement2.js$domain=ilive.to @@/afr.php?$script,domain=sankakucomplex.com @@/banman/*$script,domain=atlanticcitywebcam.com|ftlauderdalebeachcam.com|ftlauderdalewebcam.com|keywestharborwebcam.com|morganhillwebcam.com|nyharborwebcam.com|portarubawebcam.com|portbermudawebcam.com|portcanaveralwebcam.com|portevergladeswebcam.com|portmiamiwebcam.com|portnywebcam.com @@/banner.jpg?$image,domain=filmux.net @@/blockalyzer-adblock-counter/js/advertisement.js$script @@/crosdomain.xml$object-subrequest,domain=dramafever.com @@/crossdomain.xml$object-subrequest,domain=dramafever.com @@/pubads.jpeg$object-subrequest,domain=cbs.com @@/pubads.png$object-subrequest,domain=cbs.com @@/searchad.$object-subrequest,domain=cbs.com @@/wp-content/plugins/adblock-notify-by-bweb/js/advertisement.js @@/wp-content/plugins/anti-block/js/advertisement.js @@/wp-content/plugins/wordpress-adblock-blocker/adframe.js @@/wp-prevent-adblocker/*$script @@|http://$image,subdocument,third-party,domain=filmovizija.com @@|http://$image,third-party,domain=seekingalpha.com @@|http://$script,third-party,domain=eventhubs.com @@|http://$subdocument,domain=uptobox.com @@|http://*.co^$script,third-party,domain=cbs.com @@|http://*.com^*.js|$third-party,domain=cbs.com @@|http://*.jpg?$image,domain=cbs.com @@|http://*.js|$script,third-party,domain=cbs.com @@|http://*.net^*.bmp|$object-subrequest,domain=cbs.com @@|http://*.net^*.js|$third-party,domain=cbs.com @@|http://*.pw^$script,third-party,domain=cbs.com @@|http://*.tk^$script,domain=ilive.to @@|http://*.xyz^$script,third-party,domain=cbs.com @@|http://*/pubads.$object-subrequest,domain=cbs.com @@|http://*?_$image,domain=cbs.com @@|http://l.$script,third-party,domain=cbs.com @@|http://popsads.com^$script,domain=filmovizija.com @@|https://$script,domain=kissanime.com @@|https://$script,third-party,domain=cbs.com|eventhubs.com @@||247realmedia.com/RealMedia/ads/Creatives/default/empty.gif$image,domain=surfline.com @@||2mdn.net/instream/flash/v3/adsapi_$object-subrequest,domain=cbs.com @@||2mdn.net/instream/video/client.js$domain=antena3.com|atresmedia.com|atresplayer.com|lasexta.com|majorleaguegaming.com @@||300mblink.com^$elemhide @@||360haven.com/adframe.js @@||360haven.com^$elemhide @@||4fuckr.com^*/adframe.js @@||4shared.com^$script @@||4sysops.com^*/adframe.js @@||94.23.147.101^$script,domain=filmovizija.com @@||95.211.184.210/js/advertisement.js @@||95.211.194.229^$script,domain=slickvid.com @@||9msn.com.au/Services/Service.axd?*=AdExpert&$script,domain=9news.com.au @@||9tutorials.com^$elemhide @@||9xbuddy.com/js/ads.js @@||ad-emea.doubleclick.net/ad/*.CHANNEL41/*;sz=1x1;$object-subrequest,domain=channel4.com @@||ad-emea.doubleclick.net/crossdomain.xml$object-subrequest,domain=channel4.com @@||ad.doubleclick.net/|$image,domain=cwtv.com @@||ad.filmweb.pl^$script @@||ad.leadbolt.net/show_cu.js @@||ad.uptobox.com/www/delivery/ajs.php?$script @@||ad.yieldmanager.com/imp^$script,domain=watchseries-online.eu @@||ad4game.com*/images/$image,domain=kissanime.com @@||adexprt.com/cdn3/*&m=magnet$subdocument @@||adm.fwmrm.net/p/MTG_Live/Video2AdRenderer.swf$object-subrequest,domain=tv3play.se @@||admeld.com/ad/iframe/1122/pixfuture/300x250/$subdocument,domain=fileover.net @@||admeld.com/meld128.js$domain=fileover.net @@||admin.brightcove.com^$object-subrequest,domain=tvn.pl|tvn24.pl @@||adnxs.com^$script,domain=kissanime.com @@||adocean.pl^*/ad.js?id=$script,domain=tvn24.pl @@||ads.adk2.com/|$subdocument,domain=vivo.sx @@||ads.avazu.net^$subdocument,domain=casadossegredos.tv|xuuby.com @@||ads.clubedohardware.com.br/www/delivery/$script @@||ads.intergi.com^$script,domain=spoilertv.com @@||ads.lzjl.com/newserving/showad.php$domain=everythingon.tv @@||ads.milliyet.cubecdn.net/winwords/adhood/winwords2.client.js$domain=dizi-mag.com @@||ads.rubiconproject.com/ad/$domain=mangasky.co @@||ads.rubiconproject.com/ad/$script,domain=manga2u.co|mangabird.com|memegenerator.net|onemanga.me|waoanime.tv @@||ads.uptobox.com/www/delivery/ajs.php?zoneid=$script @@||ads.uptobox.com/www/images/*.png @@||adscale.de/getads.js$domain=filmovizija.com @@||adscendmedia.com/gwjs.php?$script,domain=civilization5cheats.com|kzupload.com @@||adserver.adtech.de/?adrawdata/3.0/$object-subrequest,domain=groovefm.fi|hs.fi|istv.fi|jimtv.fi|livtv.fi|loop.fi|metrohelsinki.fi|nelonen.fi|nyt.fi|radioaalto.fi|radiorock.fi|radiosuomipop.fi|ruutu.fi @@||adserver.adtech.de/?adrawdata/3.0/$script,domain=entertainment.ie @@||adserver.adtech.de/multiad/$script,domain=hardware.no|vg.no @@||adserver.liverc.com/getBannerVerify.js @@||adshost2.com/js/show_ads.js$domain=bitcoinker.com @@||adtechus.com/dt/common/postscribe.js$domain=vg.no @@||adv.wp.pl/RM/Box/*.mp4$object-subrequest,domain=wp.tv @@||advertisegame.com^$image,domain=kissanime.com @@||adverts.eclypsia.com/www/images/*.jpg|$domain=eclypsia.com @@||adzerk.net/ados.js$domain=majorleaguegaming.com @@||afdah.com^$script @@||afreesms.com/ad*.js @@||afterburnerleech.com/js/show_ads.js @@||ahctv.com^$elemhide @@||aidinge.com^$image,domain=cbs.com @@||ailde.net^$object-subrequest,domain=cbs.com @@||aildu.net^$object-subrequest,domain=cbs.com @@||airpush.com/wp-content/plugins/m-wp-popup/js/wpp-popup-frontend.js$domain=filmovizija.com @@||aka-cdn-ns.adtech.de/images/*.gif$image,domain=akam.no|amobil.no|gamer.no|hardware.no|teknofil.no @@||alcohoin-faucet.tk/advertisement.js @@||alidv.net^$object-subrequest,domain=cbs.com @@||alidw.net^$object-subrequest,domain=cbs.com @@||allkpop.com/ads.js @@||amazonaws.com/*.js$domain=cwtv.com @@||amazonaws.com/atzuma/ajs.php?adserver=$script @@||amazonaws.com/ssbss.ss/$script @@||amigosdelamili.com^$elemhide @@||amk.to/js/adcode.js? @@||ancensored.com/sites/all/modules/player/images/ad.jpg @@||android-zone.org^$elemhide @@||animalplanet.com^$elemhide @@||anime2enjoy.com^$elemhide @@||animecrave.com/_content/$script @@||anisearch.com^*/ads.js? @@||anizm.com^$elemhide @@||anonytext.tk^$elemhide @@||antena3.com/adsxml/$object-subrequest @@||anti-adblock-scripts.googlecode.com/files/adscript.js @@||apkmirror.com/wp-content/themes/APKMirror/js/ads.js @@||appfull.net^$elemhide @@||ar51.eu/ad/advertisement.js @@||arto.com/includes/js/adtech.de/script.axd/adframe.js? @@||aseanlegacy.net/ad*.js @@||aseanlegacy.net/assets/advertisement.js @@||aseanlegacy.net/images/ads.png @@||aseanlegacy.net^$elemhide @@||atresmedia.com/adsxml/$object-subrequest @@||atresplayer.com/adsxml/$object-subrequest @@||atresplayer.com/static/js/advertisement.js @@||auditude.com/player/js/lib/aud.html5player.js @@||autolikergroup.com/advertisement.js @@||avforums.com/*ad$script @@||ax-d.pixfuture.net/w/$script,domain=fileover.net @@||backin.net^$elemhide @@||bdrip.ws/web_data/*/ad$image @@||bdrip.ws^$elemhide @@||bestofmedia.com^*/advertisement.js @@||better-explorer.com^$elemhide @@||bezaldfamily.net^$elemhide @@||bitcofree.com^$elemhide @@||bitcoiner.net/advertisement.js @@||biz.tm^$script,domain=ilix.in|priva.us|urlink.at @@||blinkboxmusic.com^*/advertisement.js @@||blogspot.com^*#-$image,domain=cricket-365.pw|cricpower.com|pirlotv.tv @@||boincstats.com/js/adframe.js @@||boxxod.net/advertisement.js @@||brightcove.com^*/AdvertisingModule.swf$object-subrequest,domain=channel5.com|dave.uktv.co.uk|player.stv.tv|wwe.com @@||btspread.com/eroex.js @@||budget101.com^$elemhide @@||buysellads.com/ac/bsa.js$domain=jc-mp.com @@||bywarrior.com^$elemhide @@||c1.popads.net/pop.js$domain=go4up.com @@||captchme.net/js/advertisement-min.js @@||captchme.net/js/advertisement.js @@||casadossegredos.tv/ads/ads_$subdocument @@||caspion.com/cas.js$domain=clubedohardware.com.br @@||catchvideo.net/adframe.js @@||cbs.com^$elemhide @@||cbsistatic.com^*/advertisement.js$domain=cnet.com @@||cdn-surfline.com/ads/VolcomSurflinePlayerHo13.jpg$domain=surfline.com @@||cdnco.us^$script @@||celogeek.com/stylesheets/blogads.css @@||chango.com^*/adexchanger.png?$domain=kissanime.com @@||channel4.com/ad/l/1?|$object-subrequest @@||channel4.com/p/c4_live/ExternalHTMLAdRenderer.swf$object-subrequest @@||channel4.com/p/c4_live/PauseAdExtension.swf$object-subrequest @@||channel4.com/p/c4_live/UberlayAdRenderer.swf$object-subrequest @@||channel4.com/p/c4_live/Video2AdRenderer.swf$object-subrequest @@||channel4.com/p/c4_live/VPAIDAdRenderer.swf$object-subrequest @@||chitika.net/getads.js$domain=anisearch.com @@||chrissmoove.com^$elemhide @@||cleodesktop.com^$elemhide @@||clicksor.net/images/$domain=kissanime.com @@||clickxchange.com^$image,domain=kissanime.com @@||clkrev.com/adServe/banners?tid=$script,domain=filmovizija.com @@||clkrev.com/banners/script/$script,domain=filmovizija.com @@||cloudvidz.net^$elemhide @@||clubedohardware.com.br^$elemhide @@||codingcrazy.com/demo/adframe.js @@||coincheckin.com/js/adframe.js @@||coinracket.com^$elemhide @@||coinurl.com/get.php?id=18045 @@||concutao.tk^$script,domain=ilive.to @@||core.adprotected.com^$subdocument,domain=kissanime.com @@||cpalead.com/gwjs.php?pub=$script,domain=freebitcoinz.com|youserials.com @@||cpalead.com/mygateway.php?pub=$script,domain=free-space.net|hxcmusic.com|hxcmusic.me|justfortrendygirls.com|mmusicz.com|receive-sms.com|runescapehack.net|spotifyripping.com|stumblehere.com|tvgorge.com|tvokay.com|videodownloadx.com|wtso.net @@||cpalead.com^$domain=kissanime.com @@||cpmstar.com^$image,domain=kissanime.com @@||cpmstar.com^$script,domain=kissanime.com @@||cpmtree.com^$script,domain=kissanime.com @@||cpxinteractive.com^$script,domain=kissanime.com @@||cricket-365.tv^$elemhide @@||criteo.com/content/$image,domain=kissanime.com @@||criteo.com/delivery/ajs.php?zoneid=$script,domain=clubedohardware.com.br @@||cyberdevilz.net^$elemhide @@||d2anfhdgjxf8s1.cloudfront.net/ajs.php?adserver=$script @@||d3tlss08qwqpkt.cloudfront.net/assets/api/advertisement-$script,domain=games.softgames.de @@||dailymotion.com/embed/video/$subdocument,domain=team-vitality.fr @@||debrastagi.com^$elemhide @@||debridit.com^$elemhide @@||debridx.com^$elemhide @@||decomaniacos.es^*/advertisement.js @@||demonoid.ph^$script,domain=demonoid.ph @@||demonoid.pw^$script,domain=demonoid.pw @@||desionlinetheater.com^$elemhide @@||destinationamerica.com^$elemhide @@||destinypublicevents.com/src/advertisement.js @@||dialde.com^$domain=cbs.com @@||dinglydangly.com^$script,domain=eventhubs.com @@||dinozap.tv/adimages/ @@||directrev.com/js/gp.min.js$domain=filmovizija.com @@||discovery.com^$elemhide @@||discoverylife.com^$elemhide @@||dizi-mag.com/ads/$subdocument @@||dizicdn.com/i/ads/groupon.png$domain=dizi-mag.com @@||dlh.net^*/advertisement.js. @@||dnswatch.info^$script,domain=dnswatch.info @@||doge-faucet.tk/advertisement.js @@||dogefaucet.com^*/advertisement.js @@||dollarade.com/overlay_gateway.php?oid=$script,domain=dubs.me|filestore123.info|myfilestore.com|portable77download.blogspot.com|pspmaniaonline.com @@||dontdrinkandroot.net/js/adframe.js @@||doodle.com/builtstatic/*/doodle/js/$script @@||doubleclick.net/adj/gn.eventhubs.com/*;sz=728x90;$script,domain=eventhubs.com @@||doubleclick.net^*/adx/zattoo/video_*;cue=pre;$object-subrequest,domain=zattoo.com @@||dropboxusercontent.com/*ad$script,domain=kissanime.com @@||drugs.com^$subdocument,~third-party @@||dutplanet.net/ajax/reclamecheck.php?$xmlhttprequest @@||e24.no^$elemhide @@||ebkimg.com/banners/ @@||eclypsia.com^$script,~third-party @@||edgekey.net^*/advertisement.js$domain=play.spotify.com @@||elektrotanya.com/ads/$script,~third-party @@||elrellano.com/ad/ad.js @@||enrondev.net/ads/server/www/delivery/*&zoneid=1$subdocument,domain=filecore.co.nz @@||epicgameads.com^$image,script,domain=kissanime.com @@||epmads.com/ads?$subdocument,domain=fcportables.com @@||epmads.com/js/show_ads_epmads.js$domain=fcportables.com @@||eska.pl^*bbelements.js @@||eskago.pl/html/js/ads-banner.js @@||eskago.pl/html/js/adv.bbelements.js @@||eskago.pl/html/js/advertisement.js @@||eu5.org^*/advert.js @@||eventhubs.com^*.$script @@||exoclick.com/wp-content/themes/exoclick/images/loader.gif?$domain=xmovies8.co @@||exponential.com/tags/ClubeDoHardwarecombr/ROS/tags.js$domain=clubedohardware.com.br @@||exponential.com^*/tags.js$domain=yellowbridge.com @@||exrapidleech.info/templates/$image @@||exrapidleech.info^$elemhide,script @@||exsite.pl^*/advert.js @@||ezcast.tv/static/scripts/adscript.js @@||fastclick.net/w/get.media?sid=58322&tp=5&$script,domain=flv2mp3.com @@||fastcocreate.com/js/advertisement.js @@||fastcodesign.com/js/advertisement.js @@||fastcoexist.com/js/advertisement.js @@||fastcolabs.com/js/advertisement.js @@||fastcompany.com/js/advertisement.js @@||fasts.tv^$script,domain=ilive.to @@||fcportables.com^$elemhide @@||ffiles.com/images/mmfiles_ @@||fhscheck.zapto.org^$script,~third-party @@||fhsload.hopto.org^$script,~third-party @@||filecom.net/advertisement.js @@||fileice.net/js/advertisement.js @@||files.bannersnack.com/iframe/embed.html?$subdocument,domain=thegayuk.com @@||filmovisaprevodom.net/advertisement.js @@||filmovizija.com^$elemhide @@||filmovizija.com^$script @@||filmovizija.com^$subdocument @@||filmovizija.com^*&$image @@||filmovizija.com^*?$image @@||filmovizija.net/js/advertisement.js @@||filmovizija.net^$elemhide @@||filmovizija.net^*#$image @@||filmux.net/ads/banner.jpg? @@||filmux.org^$elemhide @@||filmweb.pl/adbanner/$script @@||firstonetv.com/ads_advertisement.js @@||firstrow*.eu^$script @@||firsttube.co^$elemhide @@||fitshr.net^$script,stylesheet @@||fm.tuba.pl/tuba3/_js/advert.js @@||fragflix.com^*.png?*=$image,domain=majorleaguegaming.com @@||free.smsmarkaz.urdupoint.com^$elemhide @@||free.smsmarkaz.urdupoint.com^*#-$image @@||freebitco.in^$script @@||freebitcoin.wmat.pl^*/advertisement.js @@||freegamehosting.nl/advertisement.js @@||freegamehosting.nl/js/advertisement.js @@||freeprosurfer.com^$elemhide @@||freesportsbet.com/js/advertisement.js @@||freshdown.net/templates/Blaster/img/*/ads/$image @@||freshdown.net^$elemhide @@||funniermoments.com/adframe.js @@||funniermoments.com^$elemhide @@||funniermoments.com^$stylesheet @@||fwcdn.pl^$script,domain=filmweb.pl @@||fwmrm.net/ad/g/1?$xmlhttprequest,domain=vevo.com @@||fwmrm.net/ad/g/1?prof=$script,domain=testtube.com @@||fwmrm.net/p/*/admanager.js$domain=adultswim.com|animalist.com|revision3.com|testtube.com @@||g.doubleclick.net/gampad/ad?iu=*/Leaderboard&sz=728x90$image,domain=magicseaweed.com @@||g.doubleclick.net/gampad/ads?*^slotname=NormalLeaderboard^$script,domain=drivearabia.com @@||g.doubleclick.net/gampad/ads?ad_rule=1&adk=*&ciu_szs=300x250&*&gdfp_req=1&*&output=xml_vast2&$object-subrequest,domain=rte.ie @@||g.doubleclick.net/gampad/adx?$object-subrequest,domain=player.muzu.tv @@||g.doubleclick.net/|$object-subrequest,domain=cbs.com @@||gallery.aethereality.net/advertisement.js @@||game-advertising-online.com/img/icon_stoplight.jpg?$domain=kissanime.com @@||game-advertising-online.com/index.php?section=serve&id=7740&subid=$subdocument,domain=anizm.com @@||gamecopyworld.com/games/$script @@||gamecopyworld.eu/games/$script @@||gamereactor.$script,~third-party @@||gamersconnexion.com/js/advert.js @@||gameshark.com/images/ads/ @@||gameslivetv.com/js/advertisement.js @@||gdataonline.com/exp/textad.js @@||genvideos.com/js/show_ads.js$domain=genvideos.com @@||go4up.com/advertisement.js @@||go4up.com^$elemhide @@||gofirstrow.eu/advertisement.js @@||gofirstrow.eu^*/advertisement.js @@||google-it.info^$script,domain=hqq.tv @@||google.com/ads/popudner/banner.jpg?$domain=magesy.be @@||googlecode.com/files/google_ads.js$domain=turkdown.com @@||googlesyndication.com/favicon.ico$domain=multiup.org @@||gscontxt.net/main/channels-jsonp.cgi?$domain=9news.com.au @@||hackers.co.id/adframe/adframe.js @@||hackintosh.zone/adblock/advertisement.js @@||hackintosh.zone^$elemhide @@||hardware.no/ads/$image @@||hardware.no/artikler/$image,~third-party @@||hardware.no^$script @@||hcpc.co.uk/*ad$script,domain=avforums.com @@||hentai-foundry.com^*/ads.js @@||hexawebhosting.com/adcode.js @@||hitcric.info^$elemhide @@||hogarutil.com^$elemhide @@||hornyspots.com^$image,domain=kissanime.com @@||hostyd.com^$elemhide @@||hpfanficarchive.com^*/advertisement.js @@||hqpdb.com/ads/banner.jpg? @@||hqq.tv^$elemhide @@||i-stream.pl^*/advertisement.js @@||i.imgur.com^*#.$image,domain=newmusicforpeople.org @@||ibmmainframeforum.com^$elemhide @@||ifirstrow.eu^$script @@||iguide.to/js/advertisement.js @@||ilive.to/js/advert*.js @@||ilive.to^$elemhide @@||ilix.in^$script,domain=ilix.in|priva.us @@||ima3vpaid.appspot.com/?adTagUrl=$object-subrequest,domain=antena3.com|atresmedia.com|atresplayer.com|lasexta.com @@||ima3vpaid.appspot.com/crossdomain.xml$object-subrequest,domain=antena3.com|atresmedia.com|atresplayer.com|lasexta.com @@||imageontime.com/ads/banner.jpg? @@||images.bangtidy.net^$elemhide @@||imasdk.googleapis.com/js/core/bridge*.html$subdocument,domain=mobinozer.com @@||imgleech.com/ads/banner.jpg? @@||imgsure.com/ads/banner.jpg? @@||in.popsads.com^$script,domain=filmovizija.com @@||incredibox.com/js/advertisement.js @@||incredibox.com/js/fuckadblock.js @@||infineoncorp.com^$domain=eventhubs.com @@||info.tm^$script,domain=ilix.in|priva.us @@||innovid.com/1x1.gif?$object-subrequest,domain=channel4.com @@||innovid.com/iroll/config/*.xml?cb=[$object-subrequest,domain=channel4.com @@||innovid.com^*/VPAIDIRollPackage.swf$object-subrequest,domain=channel4.com @@||inskinmedia.com/crossdomain.xml$object-subrequest @@||install.wtf/advertisement/advertisement.js @@||intellitxt.com/intellitxt/front.asp?ipid=$script,domain=forums.tweaktown.com @@||investigationdiscovery.com/shared/ad-enablers/ @@||investigationdiscovery.com^$elemhide @@||iriptv.com/player/ads.js @@||jjcast.com^$elemhide @@||jkanime.net/assets/js/advertisement.js @@||jkanime.net^*/advertisement2.js @@||jtvnw.net/*/advertisement.js$domain=twitch.tv @@||juba-get.com^*/advertisement.js @@||junksport.com/watch/advertisement.js @@||juzupload.com/advert*.js @@||katsomo.fi^*/advert.js @@||katsomo.fi^*/advertisement.js @@||kissanime.com/ads/$image,subdocument @@||kissanime.com^$elemhide @@||lag10.net^$elemhide @@||lasexta.com/adsxml/$object-subrequest @@||leaguesecretary.com/advertisement.js @@||leecher.us/assets/img/*/ads/$image @@||leecher.us^$elemhide @@||liberallogic101.com/show_ads.js @@||lilfile.com/js/advertise-2.js @@||lilfile.com/js/advertise.js @@||linkcrypt.ws/image/*#$image @@||linkcrypt.ws^$elemhide @@||liquidcompass.net/js/advertisement.js @@||litecoin-faucet.tk/advertisement.js @@||litecoiner.net/advertisement.js @@||livrosdoexilado.org^$elemhide @@||lordpyrak.net^$elemhide @@||lpg-forum.pl/advertise.js @@||mac2sell.net^$elemhide @@||macobserver.com/js/adlink.js @@||madadsmedia.com^$image,script,domain=kissanime.com @@||majorleaguegaming.com/live/assets/advertisement-*.js @@||majorleaguegaming.com^$elemhide @@||majorleaguegaming.com^*.png?*=$image @@||makemehost.com/js/ads.js @@||manga2u.co/css/advertiser.js @@||mangabird.com/sites/all/themes/zen/js/advertiser.js @@||mangabird.com^$elemhide @@||mangabird.me/sites/default/files/manga/*/advertise-$image @@||mangahost.com/ads.js? @@||mangakaka.com/ad/$subdocument @@||mangakaka.com^*/advertiser.js @@||marketmilitia.org/advertisement.js @@||marketmilitia.org^$elemhide @@||masfuertequeelhierro.com^$elemhide @@||mastertoons.com^$elemhide @@||maxcheaters.com/public/js/jsLoader.js @@||maxedtech.com^$elemhide @@||media.eventhubs.com/images/*#$image @@||mediaplaybox.com^$elemhide @@||megadown.us/advertisement.js @@||megahd.me^*/advertisement.js @@||megavideodownloader.com/adframe.js @@||megawypas.pl/includes/adframe.js @@||mgcash.com/common/adblock.js @@||mgcashgate.com/cpalocker/$script,domain=movieleaks.co|videodepot.org @@||mgid.com^$image,domain=kissanime.com @@||minecraft-forum.net^$elemhide @@||miniclipcdn.com/js/advertisement.js @@||mix.dj/jscripts/jquery/mdj_adverts.js @@||mix.dj^*/advertisement.js @@||mma-core.com/Scripts/adscript.js @@||mmatko.com/images/ad/$image @@||moje-dzialdowo.pl/delivery/ajs.php?zoneid=$script @@||moje-dzialdowo.pl/images/*.swf|$object @@||monsoonads.com/crossdomain.xml$object-subrequest @@||monsoonads.com:8080/crossdomain.xml$object-subrequest @@||monsoonads.com:8080/monsoon1/monsoonservice?$object-subrequest,domain=bollywoodhungama.com|videos.mid-day.com @@||moon-faucet.tk/advertisement.js @@||mousebreaker.com/scripts/ads.js @@||movie1k.net^$elemhide @@||mp3clan.com^*/advertisement.js @@||mrtzcmp3.net/advertisement.js @@||msecnd.net/scripts/compressed.pop.lib.v2.5.js$domain=filmovizija.com @@||multiup.org/img/theme/*?$image @@||muzu.tv/ads/advert.js @@||mwfiles.net/advertisement.js @@||mybannermaker.com/banner.php$~third-party @@||myfineforum.org/advertisement.js @@||myfreeforum.org/advertisement.js @@||myiplayer.com/ad*.js @@||myiplayer.com^$elemhide @@||myksn.net^$elemhide @@||mypapercraft.net^$elemhide @@||mzstatic.com^*.jpg#$image,domain=newmusicforpeople.org @@||ndtv.com/static/js/advertisement.js @@||needrom.com^$elemhide @@||nettavisen.no^*/advertisement.js @@||newmusicforpeople.org^$elemhide @@||nextthreedays.com/Include/Javascript/AdFunctions.js @@||ngads.com/*.js?$script,domain=newgrounds.com @@||nicoblog-games.com^$elemhide @@||nonags.com^$elemhide @@||nonags.com^*/ad$image @@||nosteam.ro/advertisement.js @@||nosteam.ro^*/advertisement.js @@||nzbstars.com*/advertisement.js @@||nzd.co.nz^*/ads/webads$script,domain=nzdating.com @@||olcdn.net/ads1.js$domain=olweb.tv @@||onlinemoviesfreee.com^$elemhide @@||onlinevideoconverter.com^*ad*.js @@||onvasortir.com/advert$script @@||openrunner.com/js/advertisement.js @@||openspeedtest.com/advertisement.js @@||openx.gamereactor.dk/multi.php?$script @@||openx.net/w/$script,domain=fileover.net @@||openx.net/w/1.0/acj?$script,domain=clubedohardware.com.br @@||openx.net/w/1.0/jstag$script,domain=clubedohardware.com.br @@||optimized-by.rubiconproject.com/a/$domain=manga2u.co|onemanga.me|pro-football-reference.com @@||optimized-by.rubiconproject.com/a/*-2.html?$subdocument,domain=mangasky.co @@||overclock3d.net/js/advert.js @@||own3d.tv/templates/*adsense$object-subrequest @@||own3d.tv^*_adsense.$object-subrequest @@||pagead2.googlesyndication.com/pagead/expansion_embed.js$domain=ffiles.com|full-ngage-games.blogspot.com|kingofgames.net|megaallday.com|ninjaraider.com|nonags.com|upfordown.com|wtf-teen.com @@||pagead2.googlesyndication.com/pagead/js/*/show_ads_impl.js$domain=360haven.com|9bis.net|9tutorials.com|afreesms.com|apkmirror.com|aseanlegacy.net|atlanticcitywebcam.com|bitcofree.com|bitcoiner.net|bitcoinker.com|borfast.com|budget101.com|bullywiihacks.com|chrissmoove.com|clubedohardware.com.br|darkreloaded.com|debridit.com|dev-metal.com|dreamscene.org|drivearabia.com|dsero.com|epmads.com|ezoden.com|fcportables.com|file4go.com|free.smsmarkaz.urdupoint.com|freecoins4.me|ftlauderdalebeachcam.com|ftlauderdalewebcam.com|full-ngage-games.blogspot.com|gamespowerita.com|gnomio.com|hackintosh.zone|hostyd.com|ibmmainframeforum.com|ilix.in|incredibox.com|keywestharborwebcam.com|kingofgames.net|korean-candy.com|leecher.us|litecoiner.net|livenewschat.eu|lordpyrak.net|mailbait.info|mangacap.com|masfuertequeelhierro.com|misheel.net|morganhillwebcam.com|moviemistakes.com|mypapercraft.net|needrom.com|niresh.co|niresh12495.com|nonags.com|numberempire.com|nyharborwebcam.com|omegadrivers.net|play-old-pc-games.com|portarubawebcam.com|portbermudawebcam.com|portcanaveralwebcam.com|portevergladeswebcam.com|portmiamiwebcam.com|portnywebcam.com|preemlinks.com|priva.us|puromarketing.com|radioaficion.com|rapid8.com|settlersonlinemaps.com|smashgamez.com|spoilertv.com|tech-blog.net|techydoor.com|thememypc.com|themes.themaxdavis.com|tipstank.com|trutower.com|unlocktheinbox.com|upfordown.com|uploadlw.com|urlink.at|washington.edu|whatismyip.com|winterrowd.com|yellowbridge.com|zeperfs.com @@||pagead2.googlesyndication.com/pagead/js/adsbygoogle.js$domain=activistpost.com|afreesms.com|apkmirror.com|appraisersforum.com|aseanlegacy.net|bitcofree.com|bitcoinker.com|chrissmoove.com|clubedohardware.com.br|debridit.com|demo-uhd3d.com|dev-metal.com|ezoden.com|firstonetv.com|freeprosurfer.com|gnomio.com|hackintosh.zone|i-stats.net|incredibox.com|leecher.us|mangacap.com|masfuertequeelhierro.com|mypapercraft.net|niresh.co|niresh12495.com|nonags.com|play-old-pc-games.com|settlersonlinemaps.com|unlocktheinbox.com|zeperfs.com @@||pagead2.googlesyndication.com/pagead/js/google_top_exp.js$domain=cleodesktop.com @@||pagead2.googlesyndication.com/pagead/js/lidar.js$domain=majorleaguegaming.com @@||pagead2.googlesyndication.com/pagead/show_ads.js$domain=360haven.com|9bis.net|9tutorials.com|afreesms.com|atlanticcitywebcam.com|bbc.com|bitcoiner.net|budget101.com|bullywiihacks.com|carsfromitaly.info|codeasily.com|darkreloaded.com|dreamscene.org|drivearabia.com|dsero.com|epmads.com|everythingon.tv|fcportables.com|ffiles.com|file4go.com|filmovizija.com|filmovizija.net|free.smsmarkaz.urdupoint.com|freecoins4.me|freewaregenius.com|ftlauderdalebeachcam.com|ftlauderdalewebcam.com|full-ngage-games.blogspot.com|gamespowerita.com|gifmagic.com|hackintosh.zone|hostyd.com|ibmmainframeforum.com|ilix.in|keywestharborwebcam.com|kingofgames.net|korean-candy.com|litecoiner.net|livenewschat.eu|lordpyrak.net|mangakaka.com|megaallday.com|misheel.net|morganhillwebcam.com|moviemistakes.com|needrom.com|newsok.com|ninjaraider.com|nonags.com|numberempire.com|nx8.com|nyharborwebcam.com|omegadrivers.net|photos.essence.com|portarubawebcam.com|portbermudawebcam.com|portcanaveralwebcam.com|portevergladeswebcam.com|portmiamiwebcam.com|portnywebcam.com|preemlinks.com|priva.us|puromarketing.com|radioaficion.com|rapid8.com|readersdigest.com.au|seeingwithsound.com|smashgamez.com|spoilertv.com|tech-blog.net|techydoor.com|thememypc.com|themes.themaxdavis.com|tipstank.com|top100clans.com|trutower.com|tv-kino.net|upfordown.com|uploadlw.com|urlink.at|virginmedia.com|warp2search.net|washington.edu|winterrowd.com|wtf-teen.com|yellowbridge.com @@||pagead2.googlesyndication.com/pub-config/ca-pub-$script,domain=firstonetv.com @@||pagead2.googlesyndication.com/simgad/573912609820809|$image,domain=hardocp.com @@||pandora.com/static/ads/ @@||partner.googleadservices.com/gpt/pubads_impl_$script,domain=baseball-reference.com|basketball-reference.com|hockey-reference.com|pro-football-reference.com|sports-reference.com @@||pastes.binbox.io/ad/banner?$subdocument @@||pastes.binbox.io^$elemhide @@||perkuinternete.lt/modules/mod_jpayday/js/advertisement.js @@||pes-patch.com^$elemhide @@||picu.pk^$elemhide @@||pipocas.tv/js/advertisement.js @@||pirlotv.tv^$elemhide @@||play-old-pc-games.com^$elemhide @@||playhd.eu/advertisement.js @@||playindiafilms.com/advertisement.js @@||popads.net/pop.js$domain=filmovizija.com|hqq.tv @@||popsads.com/adhandler/$script,domain=filmovizija.com @@||poreil.com^$domain=cbs.com @@||prad.de/en/$elemhide @@||premium4.us^$elemhide @@||premiumleecher.com/inc/adframe.js @@||premiumleecher.com/inc/adsense.js @@||premiumleecher.com^$elemhide @@||primeshare.tv^*/adframe.js @@||primeshare.tv^*/advertisement.js @@||primewire.ag/js/advertisement.js @@||priva.us^$script,domain=ilix.in|priva.us @@||propellerads.com^$image,domain=kissanime.com @@||protect-url.net^$script,~third-party @@||psarips.com^$script @@||puromarketing.com/js/advertisement.js @@||puromarketing.com^$elemhide @@||qrrro.com^*/adhandler/ @@||racedepartment.com^*/advertisement.js @@||rackcdn.com^$image,object-subrequest,script,domain=cbs.com @@||radar-toulouse.fr/advertisement.js @@||radioaficion.com/HamNews/*/ad$image @@||radioaficion.com^$elemhide @@||radioio.com^*/adframe.js @@||rapid8.com^$script @@||rapidmoviez.com/ad$image,subdocument @@||rapidmoviez.com/files/php/mgid-ad$subdocument @@||ratebeer.com/javascript/advertisement.js @@||rctrails.com^$script,domain=eventhubs.com @@||realidadscans.org^$elemhide @@||redtube.com*/adframe.js @@||rek.www.wp.pl/pliki/$script,domain=wp.tv @@||rek.www.wp.pl/vad.xml?$xmlhttprequest,domain=wp.tv @@||remo-xp.com^$elemhide @@||resources.infolinks.com/js/*/ice.js$domain=cyberdevilz.net @@||resources.infolinks.com/js/infolinks_main.js$domain=cyberdevilz.net @@||rincondelvago.com^*_adsense.js @@||rojadirecta.me^$elemhide @@||rsense-ad.realclick.co.kr/favicon.ico?id=$image,domain=mangaumaru.com @@||rtube.de^$elemhide @@||rubiconproject.com^$image,script,domain=kissanime.com @@||runners.es^*/advertisement.js @@||s.stooq.$script,domain=stooq.com|stooq.com.br|stooq.pl|stooq.sk @@||saavn.com/ads/search_config_ad.php?$subdocument @@||saikoanimes.net^*/advertisement.js @@||sankakucomplex.com^$script @@||sankakustatic.com^$script @@||sascdn.com/diff/js/smart.js$domain=onvasortir.com @@||sascdn.com/diff/video/$script,domain=eskago.pl @@||sascdn.com/video/$script,domain=eskago.pl @@||savevideo.me/images/banner_ads.gif @@||sawlive.tv/adscript.js @@||scan-manga.com/ads.html @@||scan-manga.com/ads/banner.jpg$image @@||sciencechannel.com^$elemhide @@||scoutingbook.com/js/adsense.js @@||search.spotxchange.com/vast/$object-subrequest,domain=maniatv.com @@||secureupload.eu^$elemhide @@||seekingalpha.com/adsframe.html#que=$subdocument @@||seekingalpha.com^$script @@||senmanga.com/advertisement.js @@||series-cravings.info/wp-content/plugins/wordpress-adblock-blocker/$script @@||sheepskinproxy.com/js/advertisement.js @@||shimory.com/js/show_ads.js @@||showsport-tv.com^$elemhide @@||siamfishing.com^*/advert.js @@||sixpool.me^$image,domain=majorleaguegaming.com @@||skidrowcrack.com/advertisement.js @@||smartadserver.com/call/pubj/*/M/*/?$domain=antena3.com|atresmedia.com|atresplayer.com|lasexta.com @@||smartadserver.com/call/pubj/*/S/*/?$domain=antena3.com|atresmedia.com|atresplayer.com|lasexta.com @@||smartadserver.com/config.js?nwid=$domain=onvasortir.com @@||sms-mmm.com/pads.js$domain=hqq.tv @@||sms-mmm.com/script.php|$script,domain=hqq.tv @@||sockshare.com/js/$script @@||sominaltvfilms.com/wp-content/*/adbanner/$image @@||sominaltvfilms.com^$elemhide @@||sonobi.com/welcome/$image,domain=kissanime.com @@||sounddrain.net^*/advertisement.js @@||spaste.com^$script @@||springstreetads.com/scripts/advertising.js @@||stackexchange.com/affiliate/ @@||static-avforums.com/*ad$script,domain=avforums.com @@||static9.net.au^*/advert.js$domain=9news.com.au @@||stooq.com.br^$elemhide,script,xmlhttprequest @@||stooq.com^$elemhide,script,xmlhttprequest @@||stooq.me^$script,domain=stooq.com|stooq.pl|stooq.sk @@||stooq.pl^$elemhide,script,xmlhttprequest @@||stooq.sk^$elemhide,script,xmlhttprequest @@||stream2watch.me^$elemhide @@||stream4free.eu^$elemhide @@||streamcloud.eu^$xmlhttprequest @@||streamin.to/adblock/advert.js @@||streamlive.to/js/ads.js @@||streamlive.to^$elemhide @@||streamlive.to^*/ad/$image @@||superplatyna.com^$elemhide @@||talksport.com/sites/default/files/ben/advert.js @@||team-vitality.fr/assets/images/advert.png @@||teenidols4you.com^$elemhide @@||teenidols4you.com^*#-$image @@||teknogods.com/advert.js @@||telemetryverification.net/crossdomain.xml$object-subrequest @@||thelordofstreaming.it/wp-content/uploads/*/ad_$image @@||thelordofstreaming.it^$elemhide @@||thememypc.com/wp-content/*/ads/$image @@||thememypc.com^$elemhide @@||thesilverforum.com/public/js/jsLoader.js?adType=$script @@||thesimsresource.com/downloads/download/itemId/$elemhide @@||thesimsresource.com/js/ads.js @@||thesominaltv.com/advertisement.js @@||thevideos.tv/js/ads.js @@||theweatherspace.com^*/advertisement.js @@||tidaltv.com/ILogger.aspx?*&adId=[$object-subrequest,domain=channel4.com @@||tidaltv.com/tpas*.aspx?*&rand=[$object-subrequest,domain=channel4.com @@||tklist.net/tklist/*ad$image @@||tklist.net^$elemhide @@||tlc.com^$elemhide @@||tpmrpg.net/adframe.js @@||tradedoubler.com/anet?type(iframe)loc($subdocument,domain=topzone.lt @@||tribalfusion.com/displayAd.js?$domain=clubedohardware.com.br @@||tribalfusion.com/j.ad?$script,domain=clubedohardware.com.br @@||trizone91.com^$elemhide @@||turkdown.com^$elemhide @@||turkdown.com^$script @@||turktorrent.cc^$elemhide @@||tv-porinternet.com.mx^$elemhide @@||tv3.co.nz/Portals/*/advertisement.js @@||tvdez.com/ads/ads_$subdocument @@||tvn.adocean.pl/files/js/ado.js$domain=tvn.pl|tvn24.pl @@||tvpelis.net^*/advertisement2.js @@||twitch.tv/ads/ads.js @@||ucoz.com/ads/banner.jpg?$image @@||uktv.co.uk/static/js/ads.js @@||up-flow.org/advertisement.js @@||uploadlw.com/getbanner.cfm?$script @@||uploadlw.com^$elemhide @@||upshare.org/advertisement.js @@||uptobox.com^*.js? @@||urbeez.com/adver$script @@||urdupoint.com/js/advertisement.js @@||urdupoint.googlecode.com/files/advertisement.js$domain=free.smsmarkaz.urdupoint.com @@||ureoal.com^$script,domain=cbs.com @@||url4u.org^$elemhide @@||urlgalleries.net^*/adhandler/$subdocument @@||usaupload.net/ads.js @@||v.fwmrm.net/ad/p/1$xmlhttprequest,domain=uktv.co.uk @@||v.fwmrm.net/ad/p/1?$object-subrequest,domain=dave.uktv.co.uk @@||vcnt3rd.com/Scripts/adscript.js$domain=mma-core.com @@||velocity.com^$elemhide @@||vencko.net^$elemhide @@||veohb.net/js/advertisement.js$domain=veohb.net @@||ver-flv.com^$elemhide @@||verticalscope.com/js/advert.js @@||vgunetwork.com/public/js/*/advertisement.js @@||video.unrulymedia.com^$script,subdocument,domain=springstreetads.com @@||videocelebrities.eu^*/adframe/ @@||videomega.tv/pub/interstitial.css @@||videomega.tv^$elemhide @@||videomega.tv^$script @@||videomega.tv^$stylesheet @@||videomega.tv^*/ad.php?id=$subdocument @@||videoplaza.tv/contrib/*/advertisement.js$domain=tv4play.se @@||vidup.me^*/adlayer.js @@||vietvbb.vn/up/clientscript/google_ads.js @@||viki.com/*.js$script @@||vipbox.tv/js/ads.js @@||vipleague.se/js/ads.js @@||vodu.ch^$script @@||wallpapermania.eu/assets/js/advertisement.js @@||wanamlite.com/images/ad/$image @@||weather.com^*/advertisement.js @@||webfirstrow.eu/advertisement.js @@||webfirstrow.eu^*/advertisement.js @@||webtv.rs/media/blic/advertisement.jpg @@||winwords.adhood.com^$script,domain=dizi-mag.com @@||world-of-hentai.to/advertisement.js @@||worldofapk.tk^$elemhide @@||wowhq.eu^$elemhide @@||writing.com^$script @@||www.vg.no^$elemhide @@||xlocker.net^$elemhide @@||xup.in^$elemhide @@||yasni.*/adframe.js @@||yellowbridge.com/ad/show_ads.js @@||yellowbridge.com^*/advertisement.js @@||yolohobo.us^$script,domain=eventhubs.com @@||youwatch.org/adframe.js @@||youwatch.org^$elemhide @@||youwatch.org^*#$image @@||ytconv.net/*google_ads.js @@||zattoo.com/ads/cs?$xmlhttprequest @@||zman.com/adv/ova/overlay.xml @@||zoomin.tv/adhandler/amalia.adm?$object-subrequest ! Non-English @@||2mdn.net/viewad/*.jpg|$domain=dafiti.cl|dafiti.com.ar|dafiti.com.br|dafiti.com.co @@||ad.doubleclick.net^*.jpg|$domain=dafiti.cl|dafiti.com.ar|dafiti.com.br|dafiti.com.co @@||ad.e-kolay.net/ad.js @@||ad.e-kolay.net/jquery-*-Medyanet.min.js @@||ad.e-kolay.net/Medyanet.js @@||ad.e-kolay.net/mnetorfad.js @@||ad.nl/ad/css/$~third-party @@||ad3.l3go.com.br^$~third-party @@||adap.tv/redir/client/swfloader.swf?$object,domain=my-magazine.me @@||adman.gr/adman-video.js$domain=alphatv.gr @@||adman.gr/jwplayer.flash.swf$object,domain=alphatv.gr @@||adocean.pl/crossdomain.xml$object-subrequest @@||adocean.pl/files/*.flv?$domain=blesk.cz|open.fm @@||adocean.pl^*/ad.js?id=$object-subrequest,domain=open.fm @@||adocean.pl^*^aocodetype=$object-subrequest @@||adpriv.nikkei.com/bservers/AAMALL/*/acc_random=$script @@||ads.cvut.cz^$~third-party @@||ads.e-planning.net^*/preroll?$object-subrequest,domain=ole.com.ar @@||ads.hosting.vcmedia.vn/crossdomain.xml$object-subrequest @@||ads.hosting.vcmedia.vn/jinfo.ashx?$object-subrequest @@||ads.nicovideo.jp/assets/js/ads-*.js @@||ads.peteava.ro/crossdomain.xml$object-subrequest @@||ads.peteava.ro/www/serve_ads/serve2.php?campaign=$object-subrequest @@||ads.postimees.ee/crossdomain.xml$object-subrequest @@||ads.telecinco.es/crossdomain.xml$object-subrequest @@||ads.telecinco.es/RealMedia/ads/adstream_sx.ads/*@$object-subrequest,domain=mitele.es|telecinco.es @@||ads.us.e-planning.net/crossdomain.xml$object-subrequest @@||ads.us.e-planning.net^*&ma=*&vv=$object-subrequest,domain=elcomercio.pe @@||adserver.netsprint.eu//widgets/widgets.js$domain=autocentrum.pl @@||adsystem.pl^$~third-party @@||adtech.de/?adrawdata/3.0/*;|$object-subrequest,domain=tv2.dk @@||adtech.panthercustomer.com^*.flv$domain=tv3.ie @@||adtechus.com/adxml|*|rettype=$object-subrequest,domain=papeldigital.info @@||adtechus.com/images/*_503x720.gif$object-subrequest,domain=papeldigital.info @@||adv.adview.pl/ads/*.mp4$object-subrequest,domain=polskieradio.pl|radiozet.pl|spryciarze.pl|tvp.info @@||adv.pt^$~third-party @@||advert.ee^$~third-party @@||advert.mgimg.com/servlet/view/$xmlhttprequest,domain=uzmantv.com @@||advert.uzmantv.com/advertpro/servlet/view/dynamic/url/zone?zid=$script,domain=uzmantv.com @@||advertising.mercadolivre.com.br^$xmlhttprequest,domain=mercadolivre.com.br @@||advertising.sun-sentinel.com/el-sentinel/elsentinel-landing-page.gif @@||affiliate.fsas.eu^$subdocument,domain=iprima.cz @@||aka-cdn-ns.adtech.de^*.flv$domain=talksport.co.uk|tv3.ie @@||akamaihd.net^*/advert/$object-subrequest,domain=skai.gr @@||alio.lt/public/advertisement/texttoimage.html?$image @@||am10.ru/letitbit.net_in.php$subdocument,domain=moevideos.net @@||amarillas.cl/advertise.do?$xmlhttprequest @@||amarillas.cl/js/advertise/$script @@||amazon-adsystem.com/e/ir?$image,domain=kasi-time.com @@||amazon-adsystem.com/widgets/q?$image,domain=kasi-time.com @@||americateve.com/mediaplayer_ads/new_config_openx.xml$xmlhttprequest @@||analytics.disneyinternational.com/ads/tagsv2/video/$xmlhttprequest,domain=disney.no @@||annonser.dagbladet.no/eas?$script,domain=se.no @@||annonser.dagbladet.no/EAS_tag.1.0.js$domain=se.no @@||app.medyanetads.com/ad.js$domain=fanatik.com.tr @@||applevideo.edgesuite.net/admedia/$object-subrequest @@||atresplayer.com/static/imgs/no_ads.jpg$object-subrequest @@||autoscout24.*/all.js.aspx?m=css&*=/stylesheets/adbanner.css @@||autotube.cz/ui/player/ad.php?id=$object-subrequest @@||bancainternet.com.ar/eBanking/images/*-PUBLICIDAD. @@||bancodevenezuela.com/imagenes/publicidad/$~third-party @@||banki.ru/bitrix/*/advertising.block/$stylesheet @@||bbelements.com/bb/bb_one2n.js$domain=moviezone.cz @@||bbelements.com/please/showit/*/?typkodu=$script,domain=idnes.cz|moviezone.cz @@||blocket.se^*/newad.js @@||bmwoglasnik.si/images/ads/ @@||bn.uol.com.br/html.ng/$object-subrequest @@||bnrs.ilm.ee/www/delivery/fl.js @@||bolha.com/css/ad.css? @@||bomnegocio.com/css/ad_insert.css @@||carfinder.gr/api/ads/$xmlhttprequest @@||catmusica.cat/paudio/getads.jsp?$xmlhttprequest @@||content.reklamz.com/internethaber/SPOR_*.mp4$object-subrequest,domain=tvhaber.com @@||custojusto.pt/user/myads/ @@||doladowania.pl/pp/$script @@||doubleclick.net/adx/es.esmas.videonot_embed/$script,domain=esmas.com @@||doubleclick.net^*;sz=*;ord=$image,script,domain=dafiti.cl|dafiti.com.ar|dafiti.com.br|dafiti.com.co @@||doublerecall.com/core.js.php?$script,domain=delo.si @@||ehow.com.br/frames/ad.html?$subdocument @@||ehowenespanol.com/frames/ad.html?$subdocument @@||emag.hu/site_ajax_ads?id=$xmlhttprequest @@||emagst.net/openx/$image,domain=emag.hu|emag.ro @@||emediate.eu/crossdomain.xml$object-subrequest @@||emediate.eu/eas?cu_key=*;ty=playlist;$object-subrequest,domain=bandit.se|lugnafavoriter.com|nrj.se|playradio.se|radio1.se|rixfm.com|tv3play.ee|tv3play.se|tv6play.se|tv8play.se @@||emediate.se/crossdomain.xml$object-subrequest @@||emediate.se/eas?$domain=novatv.bg|tv2.dk|tv3.se|tv3play.ee|tv3play.se|tv6play.se|tv8play.se @@||emediate.se/eas_tag.1.0.js$domain=tv2.dk|tv3play.ee|tv3play.se|tv6play.se|tv8play.se @@||epaper.andhrajyothy.com/js/newads.js @@||ettevotja.ee/templates/*/images/advert.gif @@||expdash.adtlgc.com^$xmlhttprequest,domain=expressen.se @@||fajerwerkilider.pl/environment/cache/images/300_250_productGfx_$image @@||feed.theplatform.com^*=adtech_$object-subrequest,domain=tv2.dk @@||filmon.com/ad/affiliateimages/banner-250x350.png @@||flashgames247.com/advertising/preroll/google-fg247-preloader.swf$object @@||forads.pl^$~third-party @@||fotojorgen.no/images/*/webadverts/ @@||fotosioon.com/wp-content/*/images/advert.gif @@||freeride.se/img/admarket/$~third-party @@||gov.in/pdf/ADVERTISEMENT/$~third-party @@||guloggratis.dk/modules/$script,~third-party,xmlhttprequest @@||haberler.com/video-haber/adsense_news_politics.swf?$object @@||happymtb.org/annonser/$~third-party @@||hizlial.com/banners/$~third-party @@||homad.eu^$~third-party @@||honfoglalo.hu/aagetad.php?$subdocument @@||hry.cz/ad/adcode.js @@||hub.com.pl/reklama_video/instream_ebmed/vStitial_inttv_$object,domain=interia.tv @@||impact-ad.jp/combo?$subdocument,domain=jalan.net @@||iplsc.com^*/inpl.box.ad.js$domain=rmf24.pl @@||isanook.com/vi/0/js/ads-$script @@||islafenice.net^*/adsense.js @@||izigo.pt/AdPictures/ @@||izigo.pt^*/adsearch? @@||jesper.nu/javascript/libs/videoads.js @@||joemonster.org^*_reklama_$image @@||kompas.com^*/supersized.*.min_ads.js? @@||kopavogur.is/umsoknarvefur/advertisement.aspx$subdocument @@||krotoszyn.pl/uploads/pub/ads_files/$image,~third-party @@||laredoute.*/scripts/combinejs.ashx?*/affiliation/$script @@||longtailvideo.com/5/adttext/adttext.js$domain=ostrow24.tv|yuvutu.com @@||longtailvideo.com/5/adtvideo/adtvideo.js$domain=ostrow24.tv @@||lrytas.lt/ads/video_feed.js @@||mail.bg/mail/index/getads/$xmlhttprequest @@||megatv.com^*/adverts.asp?$object-subrequest @@||minuripsmed.ee/templates/*/images/advert.gif @@||mjhobbymassan.se/r/annonser/$image,~third-party @@||mlstatic.com^*/product_ads/$image,domain=mercadolibre.com.ve @@||mmgastro.pl/img/reklama/$image,~third-party @@||mmgastro.pl/js/reklama/$~third-party @@||moviezone.cz//moviezone/reklama/$object-subrequest @@||moviezone.cz/swf/ad-player/$object,object-subrequest @@||muyinteresante.es/templates/muy/js/criteo.js$domain=muyinteresante.es @@||mynet.com.tr/nocache/adocean.js? @@||mynet.com/nocache/adocean.js? @@||newmedia.lu^*/adtech_video/*.xml$object-subrequest,domain=rtl.lu @@||niedziela.nl/adverts/$image,~third-party @@||nordjyske.dk/scripts/ads/StoryAds.js @@||nuggad.net/rc?nuggn=$script,domain=ekstrabladet.dk @@||oas.di.se/RealMedia/ads/Creatives/di.se/$object,script,domain=di.se @@||oas.di.se^*/di.se/Lopet/*@$script,domain=di.se @@||oas.dn.se/adstream_mjx.ads/dn.se/nyheter/ettan/*@$script @@||oascentral.gfradnetwork.net/RealMedia/ads/adstream_nx.ads/$image,domain=primerahora.com @@||openimage.interpark.com/_nip_ui/category_shopping/shopping_morningcoffee/leftbanner/null.jpg @@||openx.zomoto.nl/live/www/delivery/fl.js @@||openx.zomoto.nl/live/www/delivery/spcjs.php?id= @@||peoplegreece.com/assets/js/adtech_res.js @@||player.terra.com^*&adunit=$script @@||player.theplatform.com^$subdocument,domain=nbc.com @@||polovniautomobili.com/images/ad-$~third-party @@||prohardver.hu/js/common/forms_$script @@||propellerads.com/afu.php?zoneid=$subdocument,domain=moevideos.net @@||propellerads.com^*/adlogo/$domain=kissanime.com @@||psoe.es/Areas/Affiliation/ @@||ptchan.net/imagens/banner.php @@||ptcliente.pt/App_Themes/Default/Img/ad_$image @@||quebarato.com.br/css/static/ad_detail.css @@||quebarato.com.br/css/static/ad_search.css @@||reklama.hiking.sk/openx_new/www/delivery/spcjs.php?id=*&target=_blank$script,domain=mapy.hiking.sk @@||reklama5.mk^$~third-party @@||rentalsystems.com/advert_price_imbed.asp?$subdocument @@||ring.bg/adserver/adall.php?*&video_on_page=1 @@||rtl.lu/ipljs/adtech_async.js @@||run.admost.com/adx/get.ashx?z=*&accptck=true&nojs=1 @@||run.admost.com/adx/js/admost.js? @@||s-nk.pl/img/ads/icons_pack @@||s1emagst.akamaized.net/openx/*.jpg$domain=emag.hu @@||sanook.com/php/get_ads.php?vast_linear=$xmlhttprequest @@||sigmalive.com/assets/js/jquery.openxtag.js @@||skai.gr/advert/*.flv$object-subrequest @@||smart.allocine.fr/crossdomain.xml$object-subrequest @@||smart.allocine.fr/def/def/xshowdef.asp$object-subrequest,domain=beyazperde.com @@||smartadserver.com/call/pubj/$object-subrequest,domain=antena3.com|europafm.com|ondacero.es|vertele.com @@||smartadserver.com/call/pubx/*/M/$object-subrequest,domain=get.x-link.pl @@||smartadserver.com/call/pubx/*blq$object-subrequest,domain=antena3.com|atresmedia.com|atresplayer.com|lasexta.com @@||smartadserver.com/crossdomain.xml$object-subrequest @@||smartadserver.com/diff/*/show*.asp?*blq$object-subrequest,domain=antena3.com|atresplayer.com|lasexta.com|ondacero.es @@||sms.cz/bannery/$object-subrequest,~third-party @@||soov.ee/js/newad.js @@||staircase.pl/wp-content/*/adwords.jpg$domain=staircase.pl @@||start.no/advertpro/servlet/view/text/html/zone?zid=$script @@||start.no/includes/js/adCode.js @@||stat24.com/*/ad.xml?id=$object-subrequest,domain=ipla.tv @@||stat24.com/ad.xml?id=$object-subrequest,domain=ipla.tv @@||style.seznam.cz/ad/im.js @@||submarino.com.br/openx/www/delivery/ @@||ta3.com/advert-async-system/$xmlhttprequest @@||terra.cl^*/admanager.html$subdocument @@||terra.com.br^*/admanager.html$subdocument @@||tn.com.ar^*/vivo/300/publicidad.html$subdocument @@||trrsf.com.br/playerttv/$xmlhttprequest @@||trrsf.com.br^*/admanager.js$domain=terra.com.br @@||trrsf.com^*/admanager.js @@||tugaleaks.com^*/wp-super-popup-pro/sppro.js @@||tugaleaks.com^*/wp-super-popup-pro/sppro.php @@||tv2.dk/mpx/player.php/adtech_$subdocument @@||tvn.adocean.pl^$object-subrequest @@||uol.com.br/html.ng/*&affiliate=$object-subrequest @@||varno-zavarovanje.com/system/modules/cp_pagepeel/html/peel.js @@||velasridaura.com/modules/*/advertising_custom.$image,~third-party @@||video.appledaily.com.hk/admedia/$object-subrequest,domain=nextmedia.com @@||videonuz.ensonhaber.com/player/hdflvplayer/xml/ads.xml?$object-subrequest @@||videoplaza.tv/proxy/distributor?$object-subrequest,domain=aftenposten.no|bt.no|ekstrabladet.dk|kuriren.nu|qbrick.com|svd.se @@||vinden.se/ads/$~third-party @@||xe.gr/property/recent_ads?$xmlhttprequest @@||yapo.cl/js/viewad.js? @@||yimg.jp/images/listing/tool/yads/yjaxc-stream-ex.js$domain=yahoo.co.jp @@||ziarelive.ro/assets/js/advertisement.js ! Whitelists to fix broken pages of advertisers ! adwolf.eu @@||adwolf.eu^$~third-party ! Facebook @@||www.facebook.com/ads/$elemhide @@||www.facebook.com/ajax/ads/$xmlhttprequest,domain=www.facebook.com ! Google @@||accounts.google.com/accounts/adwords/$image,~third-party @@||accounts.google.com/adwords/$domain=accounts.google.com @@||accounts.google.com^$document,subdocument,domain=adwords.google.com @@||ads.google.com/jsapi$script,domain=www.google.com @@||adwords.google.com^$domain=adwords.google.com @@||apps.admob.com/admob/*.adsense.$script,domain=apps.admob.com @@||bpui0.google.com^$document,subdocument,domain=adwords.google.com @@||google.com/help/hc/images/adwords/$image,~third-party @@||google.com/payments/*/adwords.$document,subdocument @@||google.com/tools/feedback/open.js?*^url=https://adwords.google.com/$script,domain=adwords.google.com @@||gstatic.com/accounts/services/adwords/$image,domain=accounts.google.com @@||gstatic.com/images/icons/product/adsense-$image,domain=accounts.google.com @@||gstatic.com/images/icons/product/adsense_$image,domain=accounts.google.com @@||support.google.com/adsense/$~third-party @@||support.google.com/adwords/$~third-party @@||www.google.*/ads/css/$~third-party @@||www.google.*/ads/images/$~third-party @@||www.google.*/ads/js/$~third-party @@||www.google.*/ads/start/$~third-party @@||www.google.*/adsense/$~third-party @@||www.google.*/adwords/$~third-party @@||www.google.com/ads/admob/images/$image,domain=google.com @@||www.google.com/ads/js/$script,domain=www.google.com @@||www.google.com/adwords/$elemhide @@||www.google.com/analytics/web/$xmlhttprequest,domain=www.google.com @@||www.google.com/doubleclick/$domain=www.google.com @@||www.google.com/doubleclick/images/favicon.ico @@||www.google.com/images/icons/feature/adsense_$image @@||www.google.com/images/icons/product/adsense-$image accounts.google.com#@#.adwords ! Mobicow.com @@||adcenter.mobicow.com^$~third-party ! advertising.com @@||www.advertising.com^$~third-party ! Quantcast.com ! http://forums.lanik.us/viewtopic.php?f=64&t=15116&p=53518 @@||quantcast.com/advertise$domain=quantcast.com ! Marketgid/MGID @@||dashboard.idealmedia.com^$~third-party @@||dashboard.lentainform.com^$~third-party @@||dashboard.marketgid.com^$~third-party @@||dashboard.mgid.com^$~third-party @@||dashboard.tovarro.com^$~third-party ! Full.Ad @@||fullad.com.br^$~third-party ! Healthy Advertising (Spanish) @@||healthyadvertising.es^$~third-party ! Adfox @@||adfox.ru^$~third-party ! Apple (iAd) @@||advertising.apple.com^$domain=advertising.apple.com ! Adhese @@||adhese.com^$~third-party ! Openx.com @@||netdna-cdn.com^*/OpenX/$domain=openx.com ! Skimlinks @@||api-merchants.skimlinks.com^ @@||authentication-api.skimlinks.com^ ! Microsoft @@||advertise.bingads.microsoft.com/Includes/$domain=login.live.com @@||advertise.bingads.microsoft.com/wwimages/search/global/$image @@||advertising.microsoft.com^$~third-party @@||bingads.microsoft.com/ApexContentHandler.ashx?$script,domain=bingads.microsoft.com ! VK.ru/.com @@||paymentgate.ru/payment/*_Advert/ @@||vk.com/ads$elemhide @@||vk.com/ads.php?$subdocument,domain=vk.com @@||vk.com/ads?act=payments&type$script,stylesheet @@||vk.com/css/al/ads.css$domain=vk.com @@||vk.com/images/ads_$domain=vk.com @@||vk.com/js/al/ads.js?$domain=vk.com @@||vk.me/css/al/ads.css$domain=vk.com @@||vk.me/images/ads_$domain=vk.com ! Mxit @@||advertise.mxit.com^$~third-party ! Sanoma media @@||advertising.sanoma.be^$domain=advertising.sanoma.be ! AdRoll @@||adroll.com^$xmlhttprequest,domain=adroll.com @@||app.adroll.com^$elemhide ! Teliad @@||seedingup.*/advertiser/$~third-party,xmlhttprequest @@||teliad.*/advertiser/$~third-party,xmlhttprequest ! EasyAds @@||easyads.eu^$domain=easyads.eu ! SiteAds @@||siteads.com^$domain=siteads.com ! Amazon Associates/PartnerNet @@||amazon-adsystem.com/e/cm?$document,subdocument,domain=affiliate-program.amazon.co.uk|affiliate-program.amazon.com|affiliate-program.amazon.in|affiliate.amazon.co.jp|afiliados.amazon.es|associados.amazon.com.br|associates.amazon.ca|associates.amazon.cn|partenaires.amazon.fr|partnernet.amazon.de|programma-affiliazione.amazon.it @@||amazon-adsystem.com^$domain=affiliate-program.amazon.com @@||ssl-images-amazon.com/images/*/assoc/$image,domain=affiliate-program.amazon.co.uk|affiliate-program.amazon.com|affiliate-program.amazon.in|affiliate.amazon.co.jp|afiliados.amazon.es|associados.amazon.com.br|associates.amazon.ca|associates.amazon.cn|partenaires.amazon.fr|partnernet.amazon.de|programma-affiliazione.amazon.it @@||ssl-images-amazon.com/images/*/associate/$image,domain=affiliate-program.amazon.co.uk|affiliate-program.amazon.com|affiliate-program.amazon.in|affiliate.amazon.co.jp|afiliados.amazon.es|associados.amazon.com.br|associates.amazon.ca|associates.amazon.cn|partenaires.amazon.fr|partnernet.amazon.de|programma-affiliazione.amazon.it @@||ssl-images-amazon.com/images/*/associates/$image,domain=affiliate-program.amazon.co.uk|affiliate-program.amazon.com|affiliate-program.amazon.in|affiliate.amazon.co.jp|afiliados.amazon.es|associados.amazon.com.br|associates.amazon.ca|associates.amazon.cn|partenaires.amazon.fr|partnernet.amazon.de|programma-affiliazione.amazon.it @@||ssl-images-amazon.com/images/*_assoc_$image,domain=affiliate-program.amazon.co.uk|affiliate-program.amazon.com|affiliate-program.amazon.in|affiliate.amazon.co.jp|afiliados.amazon.es|associados.amazon.com.br|associates.amazon.ca|associates.amazon.cn|partenaires.amazon.fr|partnernet.amazon.de|programma-affiliazione.amazon.it ! Yavli.com-related @@||disqus.com/count-data.js$domain=dailycaller.com|valuewalk.com @@||newsinc.com/player/show/$domain=dailycaller.com|valuewalk.com ! Yahoo @@||eioservices.marketingsolutions.yahoo.com^$domain=eio.manhattan.yahoo.com ! Twitter @@||ads.twitter.com^$domain=ads.twitter.com|analytics.twitter.com @@||ton.twimg.com^$domain=ads.twitter.com|analytics.twitter.com ! StumbleUpon @@||ads.stumbleupon.com^$popup @@||ads.stumbleupon.com^$~third-party ! advertise.ru @@||advertise.ru^$~third-party ! acesse.com @@||ads.acesse.com^$elemhide @@||ads.acesse.com^$~third-party ! integralads.com @@||integralplatform.com/static/js/Advertiser/$~third-party ! Revealads.com @@||revealads.com^$~third-party ! *** easylist:easylist/easylist_whitelist_dimensions.txt *** @@-120x60-$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@-120x60.$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@_120_60.$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|travelplus.com @@_120x60.$image,domain=2dayshippingbymastercard.com|catalogfavoritesvip.com|chase.com|deliverydeals.co.uk|freeshipping.com|freeshippingbymastercard.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|theperfectsaver.com|travelplus.com @@_120x60_$image,domain=catalogfavoritesvip.com|freeshipping.com|freeshippingrewards.com|habandvipplus.com|inthecompanyofdogsvip.com|naturesjewelryvip.com|northstylevip.com|pyramidcollectionvip.com|serengeticatalogvip.com|theperfectsaver.com|travelplus.com @@_300x250.$image,domain=affrity.com|lockd.co.uk @@||ajax.googleapis.com/ajax/services/search/news?*-728x90&$script @@||amazonaws.com/content-images/article/*_120x60$domain=vice.com @@||amazonaws.com^*-300x250_$image,domain=snapapp.com @@||amazonaws.com^*/300x250_$image,domain=snapapp.com @@||anitasrecipes.com/Content/Images/*160x500$image @@||arnhemland-safaris.com/images/*_480_80_ @@||artserieshotels.com.au/images/*_460_60. @@||assets.vice.com^*_120x60.jpg @@||assets1.plinxmedia.net^*_300x250. @@||assets2.plinxmedia.net^*_300x250. @@||bettermarks.com/media$~third-party @@||bizquest.com^*_img/_franchise/*_120x60.$image @@||canada.com/news/*-300-250.gif @@||cdn.vidible.tv/prod/*_300x250_*.mp4| @@||cinemanow.com/images/banners/300x250/ @@||consumerist-com.wpengine.netdna-cdn.com/assets/*300x250 @@||crowdignite.com/img/upload/*300x250 @@||cubeecraft.com/images/home/features/300x250/$image,~third-party @@||dawn.com/wp-content/uploads/*_300x250.jpg @@||discovery.com^*/ratio-size/pixel-ratio/300x250.png @@||disney.com.au/global/swf/*728x90.swf @@||disney.com.au/global/swf/banner160x600.swf @@||educationpost.com.hk^*/300x250/$image @@||efvi.eu/badge/*-120x60.png @@||etsystatic.com^*_760x100.$domain=etsy.com @@||film.com/plugins/*-300x250 @@||findafranchise.com/_img/*_120x60.$image @@||firestormgames.co.uk/image/*-120x60. @@||flumotion.com/play/player?*/300x250-$subdocument,domain=flaixfm.cat @@||framestr.com^*/300x250/$image,~third-party @@||freetvhub.com/ad1_300x250.html @@||google.com/uds/modules/elements/newsshow/iframe.html?*=300x250& @@||harpers.co.uk/pictures/300x250/ @@||hortifor.com/images/*120x60$~third-party @@||images.itreviews.com/*300x250_$domain=itreviews.com @@||images.outbrain.com/imageserver/*-120x60.$image @@||imawow.weather.com/web/wow/$image @@||imdb.com/images/*doubleclick/*300x250 @@||imdb.com/images/*doubleclick/*320x240 @@||imperialwonderservices.ie/images/banner/*-468x60.$~third-party @@||komikslandia.pl/environment/cache/images/300_250_ @@||la-finca-distribution.de/wp-content/uploads/*-120x240.$image @@||maps.google.*/staticmap*^size=300x250^$image @@||maps.googleapis.com/maps/api/*=300x250& @@||marketing.beatport.com.s3.amazonaws.com^*/728x90_ @@||metrics.target.com/b/ss/*_300x250_$image @@||motherboard.tv/content-images/*_120x60. @@||mozilla.org/img/covehead/plugincheck/*/728_90/loading.png$domain=mozilla.org @@||msecnd.net/socialfactoryimagesresized/mediaspotlight/2/300x250/$image @@||mxtoolbox.com/Public/images/banners/Mx-Pro-160x600.jpg @@||nationalgeographic.com/exposure/content/*300x250 @@||onescreen.net/os/static/widgets/*300x250 @@||opposingviews.com^*/300x250/ @@||player.grabnetworks.com^*/vox_300x250_inline.xml$domain=mavrixonline.com @@||quisqualis.com/QBanner_760x100.jpg @@||static-origin.openedition.org^*-120x240.jpg @@||stickam.com/wb/www/category/300x250/$image @@||target.122.2o7.net/b/ss/*_300x250_$image,domain=target.com @@||techpakistani.com/wp-content/uploads/*-300x100.$image @@||tribune.com.ng/news2013/cache/mod_yt_k2megaslider/images/*_120_60.jpg @@||turner.com/v5cache/TCM/images/*_120x60. @@||turner.com/v5cache/TCM/Images/*_120x60_ @@||ubi.com/resource/*/game/*_300x250_$image,domain=ubi.com @@||union.edu/media/galleryPics/400x250/$~third-party @@||usanetwork.com/sites/usanetwork/*300x250 @@||usopen.org/images/pics/misc/*.300x250.jpg @@||viamichelin.*&size=728x90,$subdocument @@||vortex.accuweather.com^*_120x60_bg.jpg @@||vortex.accuweather.com^*_160x600_bg.jpg @@||vortex.accuweather.com^*_300x250_bg.jpg @@||w3easy.org/templates/*_120x60. @@||w3easy.org/templates/*_120x60_ @@||weather.craven.net.au/weather/products/300x250.asp?$image @@||weatherbug.com/desktop-weather/*=728x90& @@||weatherbug.com/images/stickers/*/728x90/ @@||weatherbug.com/style/stickers/*_728x90.css @@||wixstatic.com/media/*_300_250_$image,domain=lenislens.com @@||zorza-polarna.pl/environment/cache/images/300_250_ ! *** easylist:easylist/easylist_whitelist_popup.txt *** @@/redirect.aspx?pid=*&bid=$popup,domain=betbeaver.com @@||adfarm.mediaplex.com/ad/ck/$popup,domain=betwonga.com @@||ads.betfair.com/redirect.aspx?pid=$popup,domain=betwonga.com @@||ads.flipkart.com/delivery/ck.php?$popup,domain=flipkart.com @@||ads.pinterest.com^$popup,~third-party @@||ads.reempresa.org^$popup,domain=reempresa.org @@||ads.sudpresse.be^$popup,domain=sudinfo.be @@||ads.twitter.com^$popup,~third-party @@||ads.williamhillcasino.com/redirect.aspx?*=internal&$popup,domain=williamhillcasino.com @@||adserving.unibet.com/redirect.aspx?pid=$popup,domain=betwonga.com @@||adv.blogupp.com^$popup @@||bet365.com/home/?affiliate=$popup,domain=betbeaver.com|betwonga.com @@||doubleclick.net/click%$popup,domain=people.com|time.com @@||doubleclick.net/clk;$popup,domain=hotukdeals.com|jobamatic.com|play.google.com|santander.co.uk|techrepublic.com @@||doubleclick.net/ddm/clk/$popup,domain=couponcodeswap.com @@||g.doubleclick.net/aclk?$popup,domain=bodas.com.mx|bodas.net|casamentos.com.br|casamentos.pt|casamiento.com.uy|casamientos.com.ar|mariages.net|matrimonio.com|matrimonio.com.co|matrimonio.com.pe|matrimonios.cl|weddingspot.co.uk|zillow.com @@||gsmarena.com/adclick.php?bannerid=$popup @@||serving-sys.com/BurstingPipe/adServer.bs?$popup,domain=jobamatic.com @@||viroll.com^$popup,domain=imagebam.com|imgbox.com ! *** easylist:easylist_adult/adult_whitelist.txt *** @@||ad.thisav.com/player/jw.swf @@||ads.fuckingmachines.com^$image,~third-party @@||ads.ultimatesurrender.com^$image,~third-party @@||adv.alsscan.com^$image,stylesheet,domain=alscash.com @@||as.sexad.net/as/r?d=preroll-mov-$object-subrequest,domain=youjizz.com @@||burningcamel.com/ads/banner.jpg @@||cam4.*/ads/directory/$xmlhttprequest @@||dpmate.com/exports/tour_20/$domain=digitalplayground.com @@||eskimotube.com/advertisements.php?$script @@||fucktube.com/work/videoad.php? @@||graphics.pop6.com/javascript/live/$script @@||graphics.pop6.com/javascript/live_cd/$script @@||hostave4.net^*/video/$object-subrequest,domain=kporno.com @@||hostedadsp.realitykings.com/hosted/flash/rk_player_1.5_300x250.swf$object @@||img.livejasmin.com^$image,domain=4mycams.com @@||kuntfutube.com/go.php?ad= @@||lp.longtailvideo.com^*/adttext/adttext.js$domain=yuvutu.com @@||mrstiff.com/view/textad/$xmlhttprequest @@||nonktube.com/img/adyea.jpg @@||panicporn.com/Bannerads/player/player_flv_multi.swf$object @@||pop6.com/banners/$domain=horny.net|xmatch.com @@||promo.cdn.homepornbay.com/key=*.mp4$object-subrequest,domain=hiddencamsvideo.com @@||sextoyfun.com/admin/aff_files/BannerManager/$~third-party @@||sextoyfun.com/control/aff_banners/$~third-party @@||skimtube.com/advertisements.php? @@||starcelebs.com/logos/logo10.jpg @@||sundaysportclassifieds.co.uk/ads/$image,~third-party @@||sundaysportclassifieds.com/ads/$image,domain=sundaysportclassifieds.co.uk @@||thisav.com/uploaded_banners/jw.swf$domain=thisav.com @@||tjoob.com/go.php?ad=$script,~third-party @@||tnaflix.com/ad/$object-subrequest @@||tracking.hornymatches.com/track?type=unsubscribe&enid=$subdocument,third-party @@||widget.plugrush.com^$subdocument,domain=amateursexy.net @@||xxxporntalk.com/images/xxxpt-chrome.jpg ! Pornhub network @@||pornhub.com/channel/ @@||pornhub.com/comment/ @@||pornhub.com/front/ @@||pornhub.com/pornstar/ @@||pornhub.com/svvt/add? @@||pornhub.com/video/ @@||redtube.com/message/ @@||redtube.com/rate @@||redtube.com/starsuggestion/ @@||tube8.com/ajax/ @@||youporn.com/change/rate/ @@||youporn.com/change/user/ @@||youporn.com/change/videos/ @@||youporn.com/esi_home/subscriptions/ @@||youporn.com/mycollections.json @@||youporn.com/notifications/ @@||youporn.com/subscriptions/ ! Anti-Adblock @@.png#$domain=indiangilma.com|lfporn.com @@||adultadworld.com/adhandler/$subdocument @@||fapxl.com^$elemhide @@||fuqer.com^*/advertisement.js @@||gaybeeg.info/wp-content/plugins/blockalyzer-adblock-counter/$image,domain=gaybeeg.info @@||google.com/ads/$domain=hinduladies.com @@||hentaimoe.com/js/advertisement.js @@||imgadult.com/js/advertisement.js @@||indiangilma.com^$elemhide @@||jamo.tv^$script,domain=jamo.tv @@||javpee.com/eroex.js @@||lfporn.com^$elemhide @@||mongoporn.com^*/adframe/$subdocument @@||n4mo.org/wp-content/*/ads/ @@||n4mo.org^$elemhide @@||nightchan.com/advertisement.js @@||phncdn.com/js/advertisement.js @@||phncdn.com/v2/js/adblockdetect.js$domain=keezmovies.com @@||phncdn.com^*/ads.js @@||phncdn.com^*/fuckadblock.js @@||pornomovies.com/js/1/ads-1.js$domain=submityourflicks.com @@||pornve.com^$elemhide @@||submityourflicks.com/player/player-ads.swf$object @@||syndication.exoclick.com/ads.php?type=728x90&$script,domain=dirtstyle.tv @@||tmoncdn.com/scripts/advertisement.js$domain=tubemonsoon.com @@||trafficjunky.net/js/ad*.js @@||tube8.com/js/advertisement.js @@||xibitnet.com/check/advertisement.js @@||xibitnet.com/check/advertisements.js ! Non-English @@||ads.b10f.jp/flv/$~third-party ! *** easylist:easylist_adult/adult_whitelist_popup.txt *** @@||imagebam.com/image/$popup @@||supportchat.contentabc.com^$popup,domain=brazzerssupport.com ================================================ FILE: splash_utils/perform_actions.js ================================================ ;(function(){ var _waitAsync = waitAsync; var setTimeout = waitAsync.setTimeout; var clearTimeout = waitAsync.clearTimeout; function log() { console.log.apply(console, arguments); } function _select_set_value(select, value) { for (var i = 0, len = select.options.length; i < len; i++) { var option = select.options[ i ]; if (option.value === value) { option.selected = true; return; } } select.selectedIndex = -1; } function forEach(arr, fn){ Array.prototype.forEach.call(arr, fn); } var WAIT_ASYNC_OPTS = { maxXhr: 5, maxTimeouts: 400 }; var actions = { wait: function(data, callback){ setTimeout.call(window, callback, data.timeout); }, click: function(data, callback) { var events = ["mousemove", "mouseover", "mousedown", "mouseup", "click"]; var elements = document.querySelectorAll(data.selector); _waitAsync(function(){ forEach(elements, function(element){ var clientRect = element.getBoundingClientRect(); var clientX = clientRect.left + clientRect.width / 2; var clientY = clientRect.top + clientRect.height / 2; forEach(events, function(event){ var ev = document.createEvent("MouseEvent"); ev.initMouseEvent(event, true, true, window, 0, clientX, clientY, clientX, clientY, false, false, false, false, 0, null); element.dispatchEvent(ev); }); }); }, WAIT_ASYNC_OPTS, callback); }, scroll: function(data, callback){ var elements = document.querySelectorAll(data.selector); _waitAsync(function(){ forEach(elements, function(element){ // Scroll events in the body are dispatched on the documentElement, reverse this if(element === document.documentElement && element.scrollHeight === document.body.scrollHeight){ element = document.body; } var maxY = element.scrollMaxY || element.scrollHeight; element.scrollTop = (data.percent/100)*maxY; }); }, WAIT_ASYNC_OPTS, callback); }, set: function(data, callback) { var elements = document.querySelectorAll(data.selector); _waitAsync(function(){ forEach(elements, function(element){ var type; if(element.tagName === 'SELECT') { type = 'change'; _select_set_value(element, data.value); } else if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') { type = 'input'; element.value = data.value; } var ev = document.createEvent('Event'); ev.initEvent(type, true, false); element.dispatchEvent(ev); }); }, WAIT_ASYNC_OPTS, callback); } }; function once(fn){ var called = false; return function(){ if(!called) { called = true; return fn.apply(this, arguments); } }; } function performAction(action, callback){ callback = once(callback); try{ var tid = setTimeout.call(window, function(){ callback(); }, 2000); actions[action.type](action, function(){ clearTimeout.call(window, tid); callback(); }); }catch(e){ callback(); } } function performEvents(eventList, callback) { callback = once(callback); setTimeout.call(window, callback, 8000); function performNext() { if(eventList.length) { performAction(eventList.shift(), performNext); } else { callback(); } } performNext(); } window.__slybot__performEvents = performEvents; })(); ================================================ FILE: splash_utils/waitAsync.js ================================================ var waitAsync = (function(global){ var currentContext = null; var waitAsyncSymbol = ('Symbol' in global) ? Symbol() : '__waitAsync__symbol__'; var xhrs = 0; // http://stackoverflow.com/a/20261974/1322817 function locationOf(element, array, comparer, start, end) { if (array.length === 0) return -1; start = start || 0; end = end || array.length; var pivot = (start + end) >> 1; var c = comparer(element, array[pivot]); if (end - start <= 1) return c == -1 ? pivot - 1 : pivot; switch (c) { case -1: return locationOf(element, array, comparer, start, pivot); case 0: return pivot; case 1: return locationOf(element, array, comparer, pivot, end); } } function canUseFastTimeouts() { return waitAsync.fastTimeouts && xhrs === 0; } function openContext(ctx) { currentContext = ctx; } function notifyError(err) { oldSetTimeout(function(){ throw err; }, 0); console.error(err); } function closeContext(context){ currentContext = null; if(context.timeouts === 0 && context.xhrs === 0) { context.onFinish(); } } function wrapInContext(fn, context) { if(!context || waitAsyncSymbol in fn) return fn; var wrapped = function contextWrapper() { openContext(context); var res, err; try{ res = fn.apply(this, arguments); } catch(e) { err = e; } closeContext(context); if(err) { throw err; } return res; }; wrapped[waitAsyncSymbol] = context; return wrapped; } function compareTimeouts(t1, t2){ if (t1.time > t2.time) { return 1; } else if (t1.time < t2.time){ return -1; } else { if(t1.tid > t2.tid) { return 1; } else if (t1.tid < t2.tid) { return -1; } else { return 0; } } } function FakeDate(y, m, d, h, M, s, ms) { if(arguments.length === 0){ return new oldDate(FakeDate.now()); } else if (arguments.length === 1){ return new oldDate(y); } return new oldDate(y, m, d, h, M, s, ms); } FakeDate.timeTraveled = 0; // Length of time we have travelled, in milliseconds FakeDate.travel = function(ammount){ FakeDate.timeTraveled += ammount; }; FakeDate.now = function(){ return oldDate.now() + FakeDate.timeTraveled; }; // List of "waiting" timeout/intervals. var timeouts = []; var timeoutsByTid = {}; var lastTid = 1; function insertTimeout(fn, timeout, repeat){ if(currentContext.timeoutCredits <= 0) { return; } currentContext.timeoutCredits--; var tid = ++lastTid; timeout = Math.max(+timeout, 0); if(currentContext) { currentContext.timeouts++; } var timeoutObj = { time: FakeDate.now() + timeout, context: currentContext, fn: wrapInContext(fn, currentContext), timeout: timeout, tid: tid, repeat: repeat, cleared: false, }; timeouts.splice(locationOf(timeoutObj, timeouts, compareTimeouts) + 1, 0, timeoutObj); timeoutsByTid[tid] = timeoutObj; scheduleIfNeccessary(); return tid; } function setTimeout(fn, timeout){ return insertTimeout(fn, timeout, false); } function setInterval(fn, timeout){ return insertTimeout(fn, timeout, true); } function clearTimeout(tid) { var timeoutObj = timeoutsByTid[tid]; if(timeoutObj) { timeoutObj.context.timeoutCredits++; clearTimeoutObj(timeoutObj, true); } } function clearTimeoutObj(timeoutObj, removeFromArray){ if(timeoutObj.context) { timeoutObj.context.timeouts--; } if(removeFromArray) { var loc = locationOf(timeoutObj, timeouts, compareTimeouts); timeouts.splice(loc, 1); } delete timeoutsByTid[timeoutObj.tid]; } function clearInterval(tid) { clearTimeout(tid); } function timeTravel(){ if(canUseFastTimeouts() && timeouts.length){ FakeDate.travel(Math.max(0, timeouts[0].time - FakeDate.now())); } } function runTimeouts() { timeTravel(); while(timeouts.length && FakeDate.now() >= timeouts[0].time) { var timeoutObj = timeouts.shift(); // Run the timeout if(timeoutObj.repeat && !timeoutObj.cleared && timeoutObj.context.timeoutCredits > 0) { timeoutObj.context.timeoutCredits--; timeoutObj.time = FakeDate.now() + timeoutObj.timeout; timeouts.splice(locationOf(timeoutObj, timeouts, compareTimeouts) + 1, 0, timeoutObj); } else { clearTimeoutObj(timeoutObj, false); } try { timeoutObj.fn.call(global); } catch(e) { notifyError(e); } timeTravel(); } scheduleIfNeccessary(); } var scheduledTid = null; function scheduleIfNeccessary(){ if(scheduledTid) { oldClearTimeout(scheduledTid); } if(timeouts.length) { var time = canUseFastTimeouts() ? 0 : timeouts[0].time - FakeDate.now(); scheduledTid = oldSetTimeout(function(){ scheduledTid = null; runTimeouts(); }, time); } } function waitAsync(fn, config, callback) { if(typeof config == 'function') { callback = config; config = {}; } var ctx = { xhrCredits: typeof config.maxXhr === 'number' ? config.maxXhr : Number.MAX_VALUE, timeoutCredits: typeof config.maxTimeouts === 'number' ? config.maxTimeouts : Number.MAX_VALUE, config: config, timeouts: 0, xhrs: 0, onFinish: callback }; openContext(ctx); fn(); closeContext(ctx); } var xhrEvents = ['abort', 'error', 'load', 'loadend', 'loadstart', 'progress', 'readystatechange']; function Xhr(){ var context = currentContext; var xhr = new oldXhr(); var oldSend = patch(xhr, 'send', function(){ context = currentContext || context; if(context) { console.log('xhr credits:', context.xhrCredits); if(context.xhrCredits <= 0) { return; } context.xhrCredits--; context.xhrs++; xhrs++; } return oldSend.apply(this, arguments); }); var oldAEL = patch(xhr, 'addEventListener', function(event, fn){ return oldAEL.call(this, event, wrapInContext(fn, context)); }); function patchEventProp(event){ var handler = xhr['on' + event]; if(typeof handler === 'function' && !(waitAsyncSymbol in handler)){ xhr['on' + event] = wrapInContext(handler, context); } } xhrEvents.forEach(function(event){ oldAEL.call(xhr, event, function(){ patchEventProp(event); }); }); oldSetTimeout(function(){ xhrEvents.forEach(function(event){ patchEventProp(event); }); xhr.addEventListener('loadend', function(){ context.xhrs--; xhrs--; }); }, 0); return xhr; } function requestAnimationFrame(fn){ return setTimeout(fn, 16); } function cancelAnimationFrame(tid){ return clearTimeout(tid); } function patch(obj, key, newval) { var old = obj[key]; obj[key] = newval; return old; } var oldSetTimeout = patch(global, 'setTimeout', setTimeout); var oldSetInterval = patch(global, 'setInterval', setInterval); var oldClearInterval = patch(global, 'clearInterval', clearInterval); var oldClearTimeout = patch(global, 'clearTimeout', clearTimeout); var oldXhr = patch(global, 'XMLHttpRequest', Xhr); var oldDate = patch(global, 'Date', FakeDate); var oldRequestAnimationFrame = null; ['requestAnimationFrame', 'webkitRequestAnimationFrame', 'mozRequestAnimationFrame'].forEach(function(prop){ if(!(prop in global)) return; oldRequestAnimationFrame = patch(global, prop, requestAnimationFrame); }); var oldCancelAnimationFrame = null; ['cancelAnimationFrame', 'webkitCancelAnimationFrame', 'mozCancelAnimationFrame'].forEach(function(prop){ if(!(prop in global)) return; patch(global, prop, requestAnimationFrame); }); waitAsync.fastTimeouts = false; waitAsync.setTimeout = oldSetTimeout; waitAsync.setInterval = oldSetInterval; waitAsync.clearTimeout = oldClearTimeout; waitAsync.clearInterval = oldClearInterval; waitAsync.XMLHttpRequest = oldXhr; waitAsync.Date = oldDate; return waitAsync; })(this); ================================================ FILE: splash_utils/z_inject_this.js ================================================ // Keep a reference to some native methods, so we use the originals if // they are overridden by the page var Json = JSON; var JSONstringify = JSON.stringify; var arraySplice = Array.prototype.splice; var ArrayProto = Array.prototype; var ObjectProto = Object.prototype; var NumberProto = Number.prototype; var StringProto = String.prototype; var BooleanProto = Boolean.prototype; // Note: Variables here are not leaked to the global scope because the compiler wraps it in a function var MAX_DIALOGS = 15; // Maximum number of dialogs (alert, confirm, prompt) before throwing an exception var PortiaPage = function PortiaPage() { var that = this; this.mirrorClient = new TreeMirrorClient(document, { initialize: function(rootId, children, baseURI){ that.sendMessage('mutation', ['initialize', rootId, children, baseURI]); }, applyChanged: function(removed, addedOrMoved, attributes, text){ that.sendMessage('mutation', ['applyChanged', removed, addedOrMoved, attributes, text]); } }); }; PortiaPage.prototype.sendMutation = function(){ this.sendMessage('mutation', arraySplice.call(arguments, 0)); }; PortiaPage.prototype.sendMessage = function(action, message) { var oldAPtoJson = ArrayProto.toJSON; var oldOPtoJson = ObjectProto.toJSON; var oldNPtoJson = NumberProto.toJSON; var oldSPtoJson = StringProto.toJSON; var oldBPtoJson = BooleanProto.toJSON; delete ArrayProto.toJSON; delete ObjectProto.toJSON; delete NumberProto.toJSON; delete StringProto.toJSON; delete BooleanProto.toJSON; __portiaApi.sendMessage(JSONstringify.call(Json, [action, message])); if(oldAPtoJson) { ArrayProto.toJSON = oldAPtoJson; } if(oldOPtoJson) { ObjectProto.toJSON = oldOPtoJson; } if(oldNPtoJson) { NumberProto.toJSON = oldNPtoJson; } if(oldSPtoJson) { StringProto.toJSON = oldSPtoJson; } if(oldBPtoJson) { BooleanProto.toJSON = oldBPtoJson; } }; PortiaPage.prototype.url = function() { return window.location; }; PortiaPage.prototype.scrollX = function() { return window.scrollX; }; PortiaPage.prototype.scrollY = function() { return window.scrollY; }; PortiaPage.prototype.screenX = function() { return window.screenX; }; PortiaPage.prototype.screenY = function() { return window.screenY; }; PortiaPage.prototype.currentState = function() { return { url: this.url, scroll: { x: this.scrollX(), y: this.scrollY(), v: this.screenX(), h: this.screenY(), mx: window.scrollMaxX, my: window.scrollMaxY } }; }; PortiaPage.sendEvent = {}; PortiaPage.sendEvent.keyboard = function(element, data, type){ var ev = document.createEvent("KeyboardEvent"); ev.initKeyboardEvent(type, true, true, window, data.ctrlKey, data.altKey, data.shiftKey, data.metaKey, data.keyCode, data.charCode); element.dispatchEvent(ev); }; PortiaPage.sendEvent.simple = function(element, data, type) { var ev = document.createEvent('Event'); ev.initEvent(type, true, false); element.dispatchEvent(ev); }; PortiaPage.sendEvent.focus = function(element, data, type) { if(type in element){ element[type](); // This will trigger the event } }; PortiaPage.sendEvent.scroll = function(element, data){ // Scroll events in the body are dispatched on the documentElement, reverse this if(element === document.documentElement && element.scrollHeight === document.body.scrollHeight){ element = document.body; } // This will trigger the scroll event element.scrollTop = data.scrollTop; element.scrollLeft = data.scrollLeft; }; PortiaPage.sendEvent.unknown = function(element, data, type) { console.log('Unknown event category for event ' + type); }; PortiaPage.sendEvent.mouse = function(element, data, type) { var clientRect = element.getBoundingClientRect(); var clientX = data.targetX + clientRect.left; var clientY = data.targetY + clientRect.top; var ev = document.createEvent("MouseEvent"); ev.initMouseEvent(type, true, true, window, data.detail || 0, clientX, clientY, clientX, clientY, data.ctrlKey, data.altKey, data.shiftKey, data.metaKey, data.button, null); element.dispatchEvent(ev); }; PortiaPage.prototype.sendEvent = function(data) { var element = this.getByNodeId(data.target); if (!element) { throw new Error("Event target doesn't exist."); } Object.keys(data.propsBefore || {}).forEach(function(propName){ element[propName] = data.propsBefore[propName]; }); PortiaPage.sendEvent[data.category].call(this, element, data, data.type); Object.keys(data.propsAfter || {}).forEach(function(propName){ element[propName] = data.propsAfter[propName]; }); }; PortiaPage.prototype.getByNodeId = function(nodeId){ return this.mirrorClient.knownNodes.byId[nodeId]; }; PortiaPage.prototype.pyGetByNodeId = function(nodeId){ // Workarround to return QWebElement in python var res = this.getByNodeId(nodeId); if(res) { __portiaApi.returnElement(res); } }; var incrementDialogCounter = function(){ if(++incrementDialogCounter.count > MAX_DIALOGS) { throw new Error('Not allowed'); } }; incrementDialogCounter.count = 0; window.alert = function(){}; window.prompt = function(){ incrementDialogCounter(); return null; // dismiss the prompt (clicking cancel or closing the window) }; window.confirm = function(){ incrementDialogCounter(); return true; }; if(!('livePortiaPage' in window)){ window.livePortiaPage = new PortiaPage(); }