├── paperscraper ├── py.typed ├── exceptions.py ├── __init__.py ├── log_formatter.py ├── scraper.py ├── utils.py ├── lib.py └── headers.py ├── dev-requirements.txt ├── README.md ├── .github └── workflows │ └── lint-test.yaml ├── LICENSE ├── .pre-commit-config.yaml ├── .gitignore ├── pyproject.toml └── tests └── test_paperscraper.py /paperscraper/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dev-requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | pytest-timeout 3 | pytest-timer 4 | pre-commit 5 | -------------------------------------------------------------------------------- /paperscraper/exceptions.py: -------------------------------------------------------------------------------- 1 | class DOINotFoundError(Exception): 2 | def __init__(self, message="DOI not found"): 3 | self.message = message 4 | super().__init__(self.message) 5 | 6 | 7 | class CitationConversionError(Exception): 8 | """Exception to throw when we can't process a citation from a BibTeX.""" 9 | 10 | 11 | class NoPDFLinkError(Exception): 12 | """Exception to throw when we can't find a PDF link.""" 13 | -------------------------------------------------------------------------------- /paperscraper/__init__.py: -------------------------------------------------------------------------------- 1 | # ruff: noqa: F401 2 | 3 | from .exceptions import DOINotFoundError 4 | from .lib import ( 5 | a_gsearch_papers, 6 | a_search_papers, 7 | arxiv_to_pdf, 8 | default_scraper, 9 | format_bibtex, 10 | link_to_pdf, 11 | pmc_to_pdf, 12 | pubmed_to_pdf, 13 | search_papers, 14 | xiv_to_pdf, 15 | ) 16 | from .scraper import Scraper 17 | from .utils import check_pdf 18 | from .version import __version__ 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # paper-scraper 2 | 3 | A proof of concept to scrape papers from journals 4 | 5 | ## Install 6 | 7 | ```bash 8 | pip install git+https://github.com/blackadad/paper-scraper.git 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```python 14 | import paperscraper 15 | 16 | papers = paperscraper.search_papers('bayesian model selection', 17 | limit=10, 18 | pdir='downloaded-papers') 19 | ``` 20 | 21 | ## Note 22 | 23 | Programmatically downloading papers is a grey area. Please use this package responsibly. 24 | -------------------------------------------------------------------------------- /.github/workflows/lint-test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint and Test 3 | 4 | on: # yamllint disable-line rule:truthy 5 | pull_request: 6 | push: 7 | branches: ["main"] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | lint-test: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: actions/setup-python@v5 18 | with: 19 | cache: pip 20 | python-version: 3.11 21 | - run: python -m pip install .[dev] 22 | - uses: pre-commit/action@v3.0.1 23 | - name: test 24 | run: pytest --verbose 25 | env: 26 | SERPAPI_API_KEY: ${{ secrets.SERPAPI_API_KEY }} 27 | SEMANTIC_SCHOLAR_API_KEY: ${{ secrets.SEMANTIC_SCHOLAR_API_KEY }} 28 | -------------------------------------------------------------------------------- /paperscraper/log_formatter.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import logging 4 | from typing import ClassVar 5 | 6 | 7 | class CustomFormatter(logging.Formatter): 8 | # https://stackoverflow.com/a/56944256/2392535 9 | grey = "\x1b[38;20m" 10 | yellow = "\x1b[33;20m" 11 | red = "\x1b[31;20m" 12 | bold_red = "\x1b[31;1m" 13 | reset = "\x1b[0m" 14 | format_str = ( 15 | "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" 16 | ) 17 | 18 | FORMATS: ClassVar[dict[int, str]] = { 19 | logging.DEBUG: grey + format_str + reset, 20 | logging.INFO: grey + format_str + reset, 21 | logging.WARNING: yellow + format_str + reset, 22 | logging.ERROR: red + format_str + reset, 23 | logging.CRITICAL: bold_red + format_str + reset, 24 | } 25 | 26 | def format(self, record): 27 | log_fmt = self.FORMATS.get(record.levelno) 28 | formatter = logging.Formatter(log_fmt) 29 | return formatter.format(record) 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.6.0 4 | hooks: 5 | - id: check-added-large-files 6 | - id: check-byte-order-marker 7 | - id: check-case-conflict 8 | - id: check-merge-conflict 9 | - id: check-shebang-scripts-are-executable 10 | - id: check-symlinks 11 | - id: check-toml 12 | - id: check-yaml 13 | - id: debug-statements 14 | - id: detect-private-key 15 | - id: end-of-file-fixer 16 | - id: mixed-line-ending 17 | exclude: .gitignore 18 | - id: trailing-whitespace 19 | exclude: .gitignore 20 | - repo: https://github.com/psf/black-pre-commit-mirror 21 | rev: 24.4.2 22 | hooks: 23 | - id: black-jupyter 24 | - repo: https://github.com/astral-sh/ruff-pre-commit 25 | rev: v0.4.5 26 | hooks: 27 | - id: ruff 28 | args: [--fix, --exit-non-zero-on-fix] 29 | - repo: https://github.com/pre-commit/mirrors-prettier 30 | rev: v3.1.0 31 | hooks: 32 | - id: prettier 33 | additional_dependencies: 34 | - prettier@3.2.5 # SEE: https://github.com/pre-commit/pre-commit/issues/3133 35 | - repo: https://github.com/pappasam/toml-sort 36 | rev: v0.23.1 37 | hooks: 38 | - id: toml-sort-fix 39 | - repo: https://github.com/codespell-project/codespell 40 | rev: v2.3.0 41 | hooks: 42 | - id: codespell 43 | additional_dependencies: [".[toml]"] 44 | - repo: https://github.com/abravalheri/validate-pyproject 45 | rev: v0.18 46 | hooks: 47 | - id: validate-pyproject 48 | additional_dependencies: 49 | - "validate-pyproject-schema-store[all]" 50 | - repo: https://github.com/pre-commit/mirrors-mypy 51 | rev: v1.10.0 52 | hooks: 53 | - id: mypy 54 | additional_dependencies: # Versions here match pyproject.toml 55 | - aiohttp 56 | - pytest 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | 132 | *.pdf 133 | 134 | # Matching pyproject.toml 135 | paperscraper/version.py 136 | -------------------------------------------------------------------------------- /paperscraper/scraper.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import asyncio 4 | import logging 5 | import os 6 | from collections.abc import Awaitable, Callable, Sequence 7 | from dataclasses import dataclass 8 | from typing import Any, ClassVar, Literal 9 | 10 | from .headers import get_header 11 | from .utils import ThrottledClientSession, aidentity_fn, check_pdf 12 | 13 | 14 | @dataclass 15 | class ScraperFunction: 16 | function: Callable[..., Awaitable[bool]] 17 | priority: int 18 | kwargs: dict 19 | name: str 20 | check_pdf: bool 21 | 22 | def __str__(self) -> str: 23 | return f"{self.name} - {self.priority}" 24 | 25 | 26 | class Scraper: 27 | def __init__( 28 | self, callback: Callable[[str, dict[str, str]], Awaitable] | None = None 29 | ): 30 | self.scrapers: list[ScraperFunction] = [] 31 | self.sorted_scrapers: list[list[ScraperFunction]] = [] 32 | self.callback = callback 33 | 34 | def register_scraper( 35 | self, 36 | func, 37 | attach_session: bool = False, 38 | priority: int = 10, 39 | name: str | None = None, 40 | check: bool = True, 41 | **attached_session_kwargs, 42 | ) -> None: 43 | kwargs = {} 44 | if name is None: 45 | name = func.__name__.replace("_scraper", "") 46 | if attach_session: 47 | kwargs["session"] = ThrottledClientSession( 48 | **({"headers": get_header()} | attached_session_kwargs) 49 | ) 50 | self.scrapers.append(ScraperFunction(func, priority, kwargs, name, check)) 51 | # sort scrapers by priority 52 | self.scrapers.sort(key=lambda x: x.priority, reverse=True) 53 | # reshape into sorted scrapers 54 | self._build_sorted_scrapers() 55 | 56 | try: 57 | SCRAPE_FUNCTION_TIMEOUT: ClassVar[float | None] = float( # sec 58 | os.environ.get("PAPERSCRAPER_SCRAPE_FUNCTION_TIMEOUT", "60") 59 | ) 60 | except ValueError: # Defeat by setting to "None" 61 | SCRAPE_FUNCTION_TIMEOUT = None 62 | 63 | def _build_sorted_scrapers(self) -> None: 64 | self.sorted_scrapers = [ 65 | [s for s in self.scrapers if s.priority == priority] 66 | for priority in sorted({s.priority for s in self.scrapers}) 67 | ] 68 | 69 | def deregister_scraper(self, name: str) -> None: 70 | """Remove a scraper by name.""" 71 | for i, scraper in enumerate(self.scrapers): 72 | if scraper.name == name: 73 | self.scrapers.pop(i) 74 | break 75 | self._build_sorted_scrapers() 76 | 77 | async def scrape( 78 | self, 79 | paper: dict[str, Any], 80 | path: str | os.PathLike, 81 | i: int = 0, 82 | logger: logging.Logger | None = None, 83 | ) -> bool: 84 | """Scrape a paper which contains data from Semantic Scholar API. 85 | 86 | Args: 87 | paper (dict): A paper object from Semantic Scholar API. 88 | path: The path to save the paper. 89 | i: Optional index (e.g. batch index of the papers) used to shift 90 | the call order to load balance (e.g. 0 starts at scraper 91 | function 0, batch 1 starts at scraper function 1, etc.) 92 | logger: Optional logger to log the scraping process. 93 | """ 94 | # want highest priority first 95 | scrape_result = {s.name: "none" for s in self.scrapers} 96 | for scrapers in self.sorted_scrapers[::-1]: 97 | for j in range(len(scrapers)): 98 | scraper = scrapers[(i + j) % len(scrapers)] 99 | try: 100 | result = await asyncio.wait_for( 101 | scraper.function(paper, path, **scraper.kwargs), 102 | timeout=self.SCRAPE_FUNCTION_TIMEOUT, 103 | ) 104 | if result and ( 105 | not scraper.check_pdf or check_pdf(path, logger or False) 106 | ): 107 | scrape_result[scraper.name] = "success" 108 | if logger is not None: 109 | logger.debug( 110 | f"\tsucceeded - key: {paper['paperId']} scraper:" 111 | f" {scraper.name}" 112 | ) 113 | if self.callback is not None: 114 | await self.callback(paper["title"], scrape_result) 115 | return True 116 | except Exception: 117 | if logger is not None: 118 | logger.exception( 119 | f"\tScraper {scraper.name} failed on paper titled" 120 | f" {paper.get('title')!r}." 121 | ) 122 | scrape_result[scraper.name] = "failed" 123 | if self.callback is not None: 124 | await self.callback(paper["title"], scrape_result) 125 | return False 126 | 127 | async def batch_scrape( 128 | self, 129 | papers: Sequence[dict[str, Any]], 130 | paper_file_dump_dir: str | os.PathLike, 131 | paper_preprocessor: Callable[[Any], Awaitable[dict[str, Any]]] = aidentity_fn, 132 | paper_parser: Callable[ 133 | [dict[str, Any]], Awaitable[dict[str, Any]] 134 | ] = aidentity_fn, 135 | batch_size: int = 10, 136 | limit: int | None = None, 137 | logger: logging.Logger | None = None, 138 | ) -> dict[str, dict[str, Any]]: 139 | """ 140 | Scrape given a list of metadata. 141 | 142 | Args: 143 | papers: List of raw paper metadata. 144 | paper_file_dump_dir: Directory where papers will be downloaded. 145 | paper_preprocessor: Optional async function to process the raw paper 146 | metadata before scraping. 147 | paper_parser: Optional async function to process the raw paper metadata 148 | after scraping. 149 | batch_size: Batch size to use when scraping, within a batch 150 | scraping is parallelized. 151 | limit: Optional limit to the number of papers to scrape. 152 | logger: Optional logger to log the scraping process. 153 | 154 | Returns: 155 | Dictionary mapping path to downloaded paper to parsed metadata. 156 | """ 157 | 158 | async def scrape_parse( 159 | paper: dict[str, Any], i: int 160 | ) -> tuple[str, dict[str, Any]] | Literal[False]: 161 | try: 162 | paper = await paper_preprocessor(paper) 163 | except RuntimeError: # Failed to hydrate the required paperId 164 | if logger is not None: 165 | logger.exception(f"Failed to preprocess paper {paper}.") 166 | return False 167 | path = os.path.join(paper_file_dump_dir, f'{paper["paperId"]}.pdf') 168 | success = await self.scrape(paper, path, i=i, logger=logger) 169 | try: 170 | return (path, await paper_parser(paper)) if success else False 171 | except RuntimeError: 172 | # RuntimeError: failed to traverse link inside paper details, 173 | # or paper is missing field required for parsing like BibTeX links 174 | if logger is not None: 175 | logger.exception( 176 | f"Failed to parse paper titled {paper.get('title')!r} with key" 177 | f" {paper.get('paperId')!r}." 178 | ) 179 | return False 180 | 181 | aggregated: dict[str, dict[str, Any]] = {} 182 | for i in range(0, len(papers), batch_size): 183 | aggregated |= { 184 | r[0]: r[1] 185 | for r in await asyncio.gather(*( 186 | scrape_parse(paper=p, i=i + j) 187 | for j, p in enumerate(papers[i : i + batch_size]) 188 | )) 189 | if r is not False 190 | } 191 | if limit is not None and len(aggregated) >= limit: 192 | break 193 | return aggregated 194 | 195 | async def close(self) -> None: 196 | for scraper in self.scrapers: 197 | if "session" in scraper.kwargs: 198 | await scraper.kwargs["session"].close() 199 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | build-backend = "setuptools.build_meta" 3 | requires = ["setuptools>=64", "setuptools_scm>=8"] 4 | 5 | [project] 6 | authors = [ 7 | {email = "hello@futureforecasts.io", name = "blackadad"}, 8 | ] 9 | # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers 10 | classifiers = [ 11 | "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", 12 | "Operating System :: OS Independent", 13 | "Programming Language :: Python :: 3 :: Only", 14 | "Programming Language :: Python :: 3.10", 15 | "Programming Language :: Python :: 3.11", 16 | "Programming Language :: Python :: 3.12", 17 | "Programming Language :: Python :: 3.8", 18 | "Programming Language :: Python :: 3.9", 19 | "Programming Language :: Python", 20 | ] 21 | dependencies = [ 22 | "PyMuPDF", 23 | "aiohttp", 24 | "pybtex", 25 | ] 26 | description = "LLM Chain for answering questions from docs" 27 | dynamic = ["optional-dependencies", "version"] 28 | keywords = ["question answering"] 29 | license = {file = "LICENSE"} 30 | maintainers = [ 31 | {email = "hello@futureforecasts.io", name = "blackadad"}, 32 | {email = "jamesbraza@gmail.com", name = "James Braza"}, 33 | ] 34 | name = "paper-scraper" 35 | readme = "README.md" 36 | requires-python = ">=3.8" 37 | urls = {repository = "https://github.com/blackadad/paper-scraper"} 38 | 39 | [tool.black] 40 | enable-unstable-feature = ["hug_parens_with_braces_and_square_brackets"] 41 | preview = true 42 | 43 | [tool.codespell] 44 | check-filenames = true 45 | check-hidden = true 46 | ignore-words-list = "cros,ser" 47 | 48 | [tool.mypy] 49 | # Type-checks the interior of functions without type annotations. 50 | check_untyped_defs = true 51 | # Allows enabling one or multiple error codes globally. Note: This option will 52 | # override disabled error codes from the disable_error_code option. 53 | enable_error_code = [ 54 | "ignore-without-code", 55 | "mutable-override", 56 | "redundant-cast", 57 | "redundant-expr", 58 | "redundant-self", 59 | "truthy-bool", 60 | "truthy-iterable", 61 | "unreachable", 62 | "unused-ignore", 63 | ] 64 | # Shows a short summary line after error messages. 65 | error_summary = false 66 | # A regular expression that matches file names, directory names and paths which mypy 67 | # should ignore while recursively discovering files to check. Use forward slashes (/) as 68 | # directory separators on all platforms. 69 | exclude = [ 70 | "^\\.?venv", # SEE: https://regex101.com/r/0rp5Br/1 71 | ] 72 | # Use visually nicer output in error messages: use soft word wrap, show source 73 | # code snippets, and show error location markers. 74 | pretty = true 75 | # Shows column numbers in error messages. 76 | show_column_numbers = true 77 | # Shows error codes in error messages. 78 | # SEE: https://mypy.readthedocs.io/en/stable/error_codes.html#error-codes 79 | show_error_codes = true 80 | # Prefixes each error with the relevant context. 81 | show_error_context = true 82 | # Warns about casting an expression to its inferred type. 83 | warn_redundant_casts = true 84 | # Shows a warning when encountering any code inferred to be unreachable or 85 | # redundant after performing type analysis. 86 | warn_unreachable = true 87 | # Warns about per-module sections in the config file that do not match any 88 | # files processed when invoking mypy. 89 | warn_unused_configs = true 90 | # Warns about unneeded `# type: ignore` comments. 91 | warn_unused_ignores = true 92 | 93 | [[tool.mypy.overrides]] 94 | # Suppresses error messages about imports that cannot be resolved. 95 | ignore_missing_imports = true 96 | # Per-module configuration options 97 | module = [ 98 | "fitz", # SEE: https://github.com/pymupdf/PyMuPDF/issues/3361 99 | "nest_asyncio", 100 | "pybtex.*", # SEE: https://bitbucket.org/pybtex-devs/pybtex/issues/141/type-annotations 101 | ] 102 | 103 | [tool.pytest.ini_options] 104 | # Sets a list of filters and actions that should be taken for matched warnings. 105 | # By default all warnings emitted during the test session will be displayed in 106 | # a summary at the end of the test session. 107 | filterwarnings = [ 108 | 'ignore:open_text is deprecated. Use files\(\) instead:DeprecationWarning', # Remove after release of https://github.com/mcmtroffaes/latexcodec/issues/98 or closing of https://bitbucket.org/pybtex-devs/pybtex/issues/160/latexcodec-pylatexenc 109 | ] 110 | # Timeout in seconds for entire session. Default is None which means no timeout. 111 | # Timeout is checked between tests, and will not interrupt a test in progress. 112 | session_timeout = 2400 113 | # List of directories that should be searched for tests when no specific directories, 114 | # files or test ids are given in the command line when executing pytest from the rootdir 115 | # directory. File system paths may use shell-style wildcards, including the recursive ** 116 | # pattern. 117 | testpaths = ["tests"] 118 | # Timeout in seconds before dumping the stacks. Default is 0 which means no timeout. 119 | timeout = 300 120 | 121 | [tool.ruff] 122 | # Line length to use when enforcing long-lines violations (like `E501`). 123 | line-length = 97 # ceil(1.1 * 88) makes `E501` equivalent to `B950` 124 | # Enable application of unsafe fixes. 125 | unsafe-fixes = true 126 | 127 | [tool.ruff.lint] 128 | # List of rule codes that are unsupported by Ruff, but should be preserved when 129 | # (e.g.) validating # noqa directives. Useful for retaining # noqa directives 130 | # that cover plugins not yet implemented by Ruff. 131 | ignore = [ 132 | "ANN", # Don't care to enforce typing 133 | "BLE001", # Don't care to enforce blind exception catching 134 | "COM812", # Trailing comma with black leads to wasting lines 135 | "D100", # D100, D101, D102, D103, D104, D105, D106, D107: don't always need docstrings 136 | "D101", 137 | "D102", 138 | "D103", 139 | "D104", 140 | "D105", 141 | "D106", 142 | "D107", 143 | "D203", # Keep docstring next to the class definition (covered by D211) 144 | "D212", # Summary should be on second line (opposite of D213) 145 | "D402", # It's nice to reuse the method name 146 | "D406", # Google style requires ":" at end 147 | "D407", # We aren't using numpy style 148 | "D413", # Blank line after last section. -> No blank line 149 | "DTZ", # Don't care to have timezone safety 150 | "EM", # Overly pedantic 151 | "ERA001", # Don't care to prevent commented code 152 | "FBT001", # FBT001, FBT002: overly pedantic 153 | "FBT002", 154 | "FIX", # Don't care to prevent TODO, FIXME, etc. 155 | "FLY002", # Can be less readable 156 | "G004", # f-strings are convenient 157 | "INP001", # Can use namespace packages 158 | "N803", # Want to use 'N', or 'L', 159 | "N806", # Want to use 'N', or 'L', 160 | "PLR0913", 161 | "PTH", # Overly pedantic 162 | "S311", # Ok to use python random 163 | "SLF001", # Overly pedantic 164 | "T201", # Overly pedantic 165 | "TCH001", # TCH001, TCH002, TCH003: don't care to enforce type checking blocks 166 | "TCH002", 167 | "TCH003", 168 | "TD002", # Don't care for TODO author 169 | "TD003", # Don't care for TODO links 170 | "TID252", # Allow relative imports for packaging 171 | "TRY003", # Overly pedantic 172 | ] 173 | select = ["ALL"] 174 | unfixable = [ 175 | "B007", # While debugging, unused loop variables can be useful 176 | "ERA001", # While debugging, temporarily commenting code can be useful 177 | "F401", # While debugging, unused imports can be useful 178 | "F841", # While debugging, unused locals can be useful 179 | ] 180 | 181 | [tool.ruff.lint.flake8-annotations] 182 | mypy-init-return = true 183 | 184 | [tool.ruff.lint.per-file-ignores] 185 | "tests/*.py" = [ 186 | "PLR2004", # Tests can have magic values 187 | "S101", # Tests can have assertions 188 | ] 189 | 190 | [tool.ruff.lint.pycodestyle] 191 | # The maximum line length to allow for line-length violations within 192 | # documentation (W505), including standalone comments. 193 | max-doc-length = 97 # Match line-length 194 | 195 | [tool.ruff.lint.pydocstyle] 196 | # Whether to use Google-style or NumPy-style conventions or the PEP257 197 | # defaults when analyzing docstring sections. 198 | convention = "google" 199 | 200 | [tool.setuptools.dynamic.optional-dependencies.dev] 201 | file = ["dev-requirements.txt"] 202 | 203 | [tool.setuptools.packages.find] 204 | include = ["paperscraper*"] 205 | 206 | [tool.setuptools_scm] 207 | version_file = "paperscraper/version.py" 208 | 209 | [tool.tomlsort] 210 | all = true 211 | in_place = true 212 | spaces_before_inline_comment = 2 # Match Python PEP 8 213 | spaces_indent_inline_array = 4 # Match Python PEP 8 214 | trailing_comma_inline_array = true 215 | -------------------------------------------------------------------------------- /paperscraper/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import asyncio 4 | import hashlib 5 | import logging 6 | import os 7 | import random 8 | import re 9 | import time 10 | import urllib.parse 11 | from collections.abc import Collection 12 | from logging import Logger 13 | from typing import Literal, TypeVar, cast, overload 14 | from uuid import UUID 15 | 16 | import aiohttp 17 | import fitz 18 | 19 | from paperscraper.exceptions import NoPDFLinkError 20 | 21 | logger = logging.getLogger(__name__) 22 | 23 | 24 | class ThrottledClientSession(aiohttp.ClientSession): 25 | """ 26 | Rate-throttled client session. 27 | 28 | Original source: https://stackoverflow.com/a/60357775 29 | """ 30 | 31 | MAX_WAIT_FOR_CLOSE = 6.0 # sec 32 | TIME_BASE = MAX_WAIT_FOR_CLOSE - 1 # sec 33 | 34 | def __init__( 35 | self, rate_limit: float | None = None, retry_count: int = 5, *args, **kwargs 36 | ) -> None: 37 | """ 38 | Initialize. 39 | 40 | Args: 41 | rate_limit: Optional number of requests per second to throttle. If left as 42 | None, no throttling is applied. 43 | retry_count: Number of retries to attempt on service limit status codes, set 44 | to 0 to disable retries. 45 | *args: Positional arguments to pass to aiohttp.ClientSession.__init__. 46 | **kwargs: Keyword arguments to pass to aiohttp.ClientSession.__init__. 47 | """ 48 | super().__init__(*args, **kwargs) 49 | self._rate_limit = rate_limit 50 | self._retry_count = retry_count 51 | self._start_time = time.time() 52 | if rate_limit is not None: 53 | queue_size = int(rate_limit * self.TIME_BASE) 54 | if queue_size < 1: 55 | raise ValueError( 56 | f"Rate limit {rate_limit} is too low for a responsive close, please" 57 | f" increase to at least {1 / self.TIME_BASE} requests/sec." 58 | ) 59 | self._queue: asyncio.Queue | None = asyncio.Queue(maxsize=queue_size) 60 | self._fillerTask: asyncio.Task | None = asyncio.create_task(self._filler()) 61 | else: 62 | self._queue = None 63 | self._fillerTask = None 64 | 65 | async def close(self) -> None: 66 | """Close rate-limiter's "bucket filler" task.""" 67 | if self._fillerTask is not None: 68 | # There exists an edge case where an empty session gets closed 69 | # before the filler task even starts. In this edge case, we employ 70 | # a small asyncio sleep to give a chance to start the filler task. 71 | await asyncio.sleep(delay=1e-3) 72 | self._fillerTask.cancel() 73 | await asyncio.wait_for(self._fillerTask, timeout=self.MAX_WAIT_FOR_CLOSE) 74 | await super().close() 75 | 76 | async def _filler(self) -> None: 77 | """Filler task to fill the leaky bucket algo.""" 78 | if self._rate_limit is None: 79 | return 80 | queue = cast(asyncio.Queue, self._queue) 81 | # This sleep interval (sec) is enough to enqueue at least 1 request 82 | # - If 1 / rate_limit is above 1e-3, we should add on average 1 request 83 | # to the queue per below loop iteration 84 | # - Otherwise, we'll add on average above 1 request to the queue per 85 | # below loop iteration 86 | sleep_interval = max(1 / self._rate_limit, 1e-3) # sec 87 | ts_before_sleep = time.perf_counter() 88 | try: 89 | while True: 90 | ts_after_sleep = time.perf_counter() 91 | # Calculate how many requests to add to the bucket based on elapsed time. 92 | num_requests_to_add = int( 93 | (ts_after_sleep - ts_before_sleep) * self._rate_limit 94 | ) 95 | # Calculate available space in the queue to avoid overfilling it. 96 | available_space = queue.maxsize - queue.qsize() 97 | # Only add as many requests as there is space. 98 | for _ in range(min(num_requests_to_add, available_space)): 99 | # Insert a request (represented as None) into the queue 100 | queue.put_nowait(None) 101 | 102 | ts_before_sleep = ts_after_sleep 103 | await asyncio.sleep(sleep_interval) 104 | except asyncio.CancelledError: 105 | pass 106 | except Exception: 107 | logger.exception("Unexpected failure in queue filling.") 108 | 109 | async def _wait_can_make_request(self) -> None: 110 | if self._queue is not None: 111 | await self._queue.get() 112 | self._queue.task_done() 113 | 114 | SERVICE_LIMIT_REACHED_STATUS_CODES: Collection[int] = {429, 503} 115 | 116 | async def _request(self, *args, **kwargs) -> aiohttp.ClientResponse: 117 | for retry_num in range(self._retry_count + 1): 118 | await self._wait_can_make_request() 119 | response = await super()._request(*args, **kwargs) 120 | if response.status not in self.SERVICE_LIMIT_REACHED_STATUS_CODES: 121 | break 122 | if retry_num < self._retry_count: 123 | exp_backoff_with_jitter = 0.1 * (2**retry_num + random.random()) 124 | logger.warning( 125 | f"Hit a service limit per status {response.status} with message" 126 | f" {await response.text()}, sleeping" 127 | f" {exp_backoff_with_jitter:.2f}-sec before retry {retry_num + 1}." 128 | ) 129 | await asyncio.sleep(exp_backoff_with_jitter) 130 | # NOTE: on next iteration, we have to wait again, which ensures 131 | # the rate_limit is adhered to 132 | continue 133 | else: 134 | raise RuntimeError( 135 | f"Failed to avoid a service limit across {self._retry_count} retries." 136 | ) 137 | return response 138 | 139 | 140 | def check_pdf(path: str | os.PathLike, verbose: bool | Logger = False) -> bool: 141 | path = str(path) 142 | if not os.path.exists(path): 143 | return False 144 | 145 | try: 146 | # Open the PDF file using fitz 147 | with fitz.open(path): 148 | pass # For now, just opening the file is our basic check 149 | 150 | except fitz.FileDataError as e: 151 | if verbose and isinstance(verbose, bool): 152 | print(f"PDF at {path} is corrupt or unreadable: {e}") 153 | elif verbose: 154 | verbose.exception(f"PDF at {path} is corrupt or unreadable.", exc_info=e) 155 | return False 156 | 157 | return True 158 | 159 | 160 | # SEE: https://www.crossref.org/blog/dois-and-matching-regular-expressions/ 161 | # Test cases: https://regex101.com/r/xtI5bS/10 162 | pattern = r"\/(10.\d{4,9}(?:[\/\.][a-z-().]*(?:[-<>()\/;:\w]*\d+[-<>();:\w]*)+)+)" 163 | compiled_pattern = re.compile(pattern, re.IGNORECASE) 164 | 165 | 166 | @overload 167 | def find_doi(text: str, disallow_no_match: Literal[True]) -> str: ... 168 | @overload 169 | def find_doi(text: str, disallow_no_match: Literal[False] = False) -> str | None: ... 170 | def find_doi(text: str, disallow_no_match: bool = False) -> str | None: 171 | match = compiled_pattern.search(urllib.parse.unquote(text)) 172 | if not match: 173 | if disallow_no_match: 174 | raise ValueError(f"Failed to find DOI in {text!r}.") 175 | return None 176 | return match.group(1) 177 | 178 | 179 | def encode_id(value: str | bytes | UUID, maxsize: int | None = 16) -> str: 180 | """Encode a value (e.g. a DOI) optionally with a max length.""" 181 | if isinstance(value, UUID): 182 | value = str(value) 183 | if isinstance(value, str): 184 | value = value.lower().encode() 185 | return hashlib.md5(value).hexdigest()[:maxsize] # noqa: S324 186 | 187 | 188 | def get_scheme_hostname(url: str) -> str: 189 | parsed_url = urllib.parse.urlparse(url) 190 | return urllib.parse.ParseResult( 191 | scheme=parsed_url.scheme, 192 | netloc=parsed_url.netloc, 193 | path="", 194 | params="", 195 | query="", 196 | fragment="", 197 | ).geturl() 198 | 199 | 200 | def search_pdf_link(text: str, epdf: bool = False) -> str: 201 | if epdf: 202 | epdf_link = re.search(r'href="(\S+\.epdf)"', text) 203 | if epdf_link: 204 | return epdf_link.group(1).replace("epdf", "pdf") 205 | else: 206 | pdf_link = re.search(r'href="(\S+\.pdf)"', text) 207 | if pdf_link: 208 | return pdf_link.group(1) 209 | raise NoPDFLinkError("No PDF link found.") 210 | 211 | 212 | def crossref_headers(): 213 | """Crossref API key if available, otherwise nothing.""" 214 | if api_key := os.environ.get("CROSSREF_API_KEY"): 215 | return {"Crossref-Plus-API-Token": f"Bearer {api_key}"} 216 | return {} 217 | 218 | 219 | T = TypeVar("T") 220 | 221 | 222 | async def aidentity_fn(x: T) -> T: 223 | return x 224 | -------------------------------------------------------------------------------- /tests/test_paperscraper.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import asyncio 4 | import contextlib 5 | import os 6 | import tempfile 7 | import time 8 | from functools import partial 9 | from unittest import IsolatedAsyncioTestCase 10 | from unittest.mock import AsyncMock, MagicMock, patch 11 | 12 | import aiohttp 13 | import pytest 14 | from aiohttp import ClientResponseError 15 | from pybtex.database import parse_string 16 | 17 | import paperscraper 18 | from paperscraper.exceptions import ( 19 | CitationConversionError, 20 | DOINotFoundError, 21 | NoPDFLinkError, 22 | ) 23 | from paperscraper.headers import get_header 24 | from paperscraper.lib import ( 25 | GOOGLE_SEARCH_MAX_PAGE_SIZE, 26 | RateLimits, 27 | clean_upbibtex, 28 | doi_to_bibtex, 29 | format_bibtex, 30 | openaccess_scraper, 31 | parse_google_scholar_metadata, 32 | reconcile_doi, 33 | ) 34 | from paperscraper.utils import ( 35 | ThrottledClientSession, 36 | encode_id, 37 | find_doi, 38 | search_pdf_link, 39 | ) 40 | 41 | 42 | class TestThrottledClientSession(IsolatedAsyncioTestCase): 43 | async def test_throttling(self) -> None: 44 | 45 | async def get(session_: aiohttp.ClientSession) -> None: 46 | async with session_.get( 47 | "http://example.com", timeout=aiohttp.ClientTimeout(3.0) 48 | ) as response: 49 | response.raise_for_status() 50 | await response.text() 51 | 52 | tic = time.perf_counter() 53 | async with ThrottledClientSession() as session: 54 | await asyncio.gather(*(get(session) for _ in range(6))) 55 | assert time.perf_counter() - tic < 1, "Expected no throttling" 56 | 57 | tic = time.perf_counter() 58 | async with ThrottledClientSession(rate_limit=2) as session: 59 | await asyncio.gather(*(get(session) for _ in range(6))) 60 | assert 2.5 <= time.perf_counter() - tic <= 4.0, "Expected throttling" 61 | 62 | async def test_can_timeout(self) -> None: 63 | for rate_limit in (None, 1): 64 | async with ThrottledClientSession(rate_limit=rate_limit) as session: 65 | tic = time.perf_counter() 66 | try: 67 | async with session.get( 68 | # This URL should always timeout 69 | "http://example.com:81", 70 | timeout=aiohttp.ClientTimeout(3.0), 71 | ): 72 | pass 73 | except asyncio.TimeoutError: 74 | toc = time.perf_counter() 75 | assert 3.0 <= toc - tic <= 5.0, "Expected timeout" 76 | else: 77 | raise AssertionError( 78 | f"Should have timed out with rate limit {rate_limit}." 79 | ) 80 | 81 | async def test_empty_session(self) -> None: 82 | """Check an empty session doesn't crash us.""" 83 | async with ThrottledClientSession(rate_limit=30.0): 84 | pass 85 | 86 | async def test_service_limit(self) -> None: 87 | async with ThrottledClientSession(rate_limit=10.0) as session: 88 | with ( 89 | patch.object( 90 | aiohttp.ClientSession, 91 | "_request", 92 | wraps=partial(aiohttp.ClientSession._request, session), 93 | ) as mock_request, 94 | pytest.raises(RuntimeError, match="service limit"), 95 | ): 96 | await session.get( 97 | "http://httpbin.org/status/429", headers={"accept": "text/plain"} 98 | ) 99 | assert ( 100 | mock_request.call_count == 6 101 | ), "Expected first attempt followed by 5 retries" 102 | 103 | 104 | class TestCrossref(IsolatedAsyncioTestCase): 105 | async def test_reconcile_dois(self) -> None: 106 | session = ThrottledClientSession( 107 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 108 | ) 109 | doi = "10.1056/nejmoa2200674" 110 | 111 | bibtex = await doi_to_bibtex(doi, session) 112 | assert bibtex 113 | 114 | # get title 115 | title = bibtex.split("title={")[1].split("},")[0] 116 | assert await reconcile_doi(title, [], session) == doi 117 | 118 | # format 119 | key = bibtex.split("{")[1].split(",")[0] 120 | assert format_bibtex(bibtex, key, clean=False) 121 | 122 | async def test_hard_reconciles(self): 123 | test_parameters: list[dict] = [ 124 | { 125 | "title": ( 126 | "High-throughput screening of human genetic variants by pooled" 127 | " prime editing." 128 | ), 129 | "doi": "10.1101/2024.04.01.587366", 130 | }, 131 | { 132 | "title": ( 133 | "High-throughput screening of human genetic variants by pooled" 134 | " prime editing." 135 | ), 136 | "authors": ["garbage", "authors", "that"], 137 | "doi": "10.1101/2024.04.01.587366", 138 | }, 139 | { 140 | "title": ( 141 | "High throughput screening of human genetic variants by pooled" 142 | " prime editing" 143 | ), 144 | "doi": "10.1101/2024.04.01.587366", 145 | }, 146 | ] 147 | session = ThrottledClientSession(headers=get_header(), rate_limit=15 / 60) 148 | for test in test_parameters: 149 | assert await reconcile_doi(test["title"], [], session) == test["doi"] 150 | 151 | 152 | def test_find_doi() -> None: 153 | test_parameters = [ 154 | ("", None), 155 | ("https://www.sciencedirect.com/science/article/pii/S001046551930373X", None), 156 | ("https://www.academia.edu/download/110406132/2.pdf", None), 157 | ("https://doi.org/10.1056/nejmoa2200674", "10.1056/nejmoa2200674"), 158 | ( 159 | "https://www.biorxiv.org/content/10.1101/2024.01.31.578268v1", 160 | "10.1101/2024.01.31.578268v1", 161 | ), 162 | ( 163 | "https://www.biorxiv.org/content/10.1101/2024.01.31.578268v1.full-text", 164 | "10.1101/2024.01.31.578268v1", 165 | ), 166 | ( 167 | "https://www.taylorfrancis.com/chapters/edit/10.1201/9781003240037-2/impact-covid-vaccination-globe-using-data-analytics-pawan-whig-arun-velu-rahul-reddy-pavika-sharma", 168 | "10.1201/9781003240037-2", 169 | ), 170 | ( 171 | "https://iopscience.iop.org/article/10.7567/1882-0786/ab5c44/meta", 172 | "10.7567/1882-0786/ab5c44", 173 | ), 174 | ( 175 | "https://iopscience.iop.org/article/10.7567/abc123abc/meta", 176 | "10.7567/abc123abc", 177 | ), 178 | ( 179 | "https://iopscience.iop.org/article/10.7567/abc123abc.pdf", 180 | "10.7567/abc123abc", 181 | ), 182 | ( 183 | "https://dx.doi.org/10.1016/j.arth.2005.04.023", 184 | "10.1016/j.arth.2005.04.023", 185 | ), 186 | ("https://doi.org/10.48550/arXiv.2401.00044", "10.48550/arXiv.2401.00044"), 187 | ( 188 | "https://doi.org/10.26434/chemrxiv-2023-fw8n4-v3", 189 | "10.26434/chemrxiv-2023-fw8n4-v3", 190 | ), 191 | ( 192 | "https://www.biorxiv.org/content/10.1101/2022.08.05.502972.full.pdf", 193 | "10.1101/2022.08.05.502972", 194 | ), 195 | ( 196 | "https://doi.org/10.1002/(SICI)1097-0177(200006)218:2%3C235::AID-DVDY2%3E3.0.CO;2-G", 197 | "10.1002/(SICI)1097-0177(200006)218:2<235::AID-DVDY2>3.0.CO;2-G", 198 | ), 199 | ( 200 | "https://anatomypubs.onlinelibrary.wiley.com/doi/10.1002/(SICI)1097-0177(200006)218:2%3C235::AID-DVDY2%3E3.0.CO;2-G", 201 | "10.1002/(SICI)1097-0177(200006)218:2<235::AID-DVDY2>3.0.CO;2-G", 202 | ), 203 | ("https://doi.org/10.1093/nar/gkae222", "10.1093/nar/gkae222"), 204 | ( 205 | "https://doi.org/10.1007/s13592-019-00684-x?wt_mc=internal.event.1.sem.articleauthoronlinefirst&utm_source=articleauthoronlinefirst&utm_medium=email&utm_content=aa_en_06082018&articleauthoronlinefirst_20190913&fbclid=iwar2ipcqh8tqoyocdb2ryt-rqf2slmyf3s4k5_qwonmipan9_nqc_wiuabhi", 206 | "10.1007/s13592-019-00684-x", 207 | ), 208 | ] 209 | for link, expected in test_parameters: 210 | if expected is None: 211 | assert find_doi(link) is None 212 | else: 213 | assert find_doi(link) == expected 214 | 215 | 216 | def test_encode_id() -> None: 217 | assert ( 218 | encode_id("10.1056/nejmoa2119451") 219 | == encode_id("10.1056/NEJMOA2119451") 220 | == "945f1f30b11bcae6" 221 | ) 222 | 223 | 224 | def test_format_bibtex_badkey(): 225 | bibtex1 = """ 226 | @article{Moreira2022Safety, 227 | title = {Safety and Efficacy of a Third Dose of BNT162b2 Covid-19 Vaccine}, 228 | volume = {386}, 229 | ISSN = {1533-4406}, 230 | url = {http://dx.doi.org/10.1056/nejmoa2200674}, 231 | DOI = {10.1056/nejmoa2200674}, 232 | number = {20}, 233 | journal = {New England Journal of Medicine}, 234 | publisher = {Massachusetts Medical Society}, 235 | author = {Moreira, Edson D. and Kitchin, Nicholas and Xu, Xia and Dychter, Samuel S. and Lockhart, Stephen and Gurtman, Alejandra and Perez, John L. and Zerbini, Cristiano and Dever, Michael E. and Jennings, Timothy W. and Brandon, Donald M. and Cannon, Kevin D. and Koren, Michael J. and Denham, Douglas S. and Berhe, Mezgebe and Fitz-Patrick, David and Hammitt, Laura L. and Klein, Nicola P. and Nell, Haylene and Keep, Georgina and Wang, Xingbin and Koury, Kenneth and Swanson, Kena A. and Cooper, David and Lu, Claire and Türeci, Özlem and Lagkadinou, Eleni and Tresnan, Dina B. and Dormitzer, Philip R. and Şahin, Uğur and Gruber, William C. and Jansen, Kathrin U.}, 236 | year = {2022}, 237 | month = may, 238 | pages = {1910-1921} 239 | } 240 | """ # noqa: E501 241 | assert format_bibtex(bibtex1, "Moreira2022Safety", clean=False) 242 | 243 | 244 | class Test0(IsolatedAsyncioTestCase): 245 | async def test_google_search_papers(self) -> None: 246 | for query, year, limit in [ 247 | ("molecular dynamics", "2019-2023", 5), 248 | ("molecular dynamics", "2020", 5), 249 | ("covid vaccination", None, 10), 250 | ]: 251 | with self.subTest(): 252 | papers = await paperscraper.a_search_papers( 253 | query, search_type="google", year=year, limit=limit 254 | ) 255 | assert len(papers) >= 3 256 | 257 | async def test_with_multiple_google_search_pages(self) -> None: 258 | papers = await paperscraper.a_search_papers( 259 | "molecular dynamics", 260 | search_type="google", 261 | year="2019-2023", 262 | limit=int(2.1 * GOOGLE_SEARCH_MAX_PAGE_SIZE), 263 | ) 264 | assert len(papers) > GOOGLE_SEARCH_MAX_PAGE_SIZE 265 | 266 | 267 | class TestGSearch(IsolatedAsyncioTestCase): 268 | async def test_gsearch(self): 269 | query = "molecular dynamics" 270 | papers = await paperscraper.a_gsearch_papers(query, year="2019-2023", limit=3) 271 | assert len(papers) >= 3 272 | 273 | # check their details 274 | for paper in papers.values(): 275 | assert paper["citation"] 276 | assert paper["key"] 277 | assert paper["url"] 278 | assert paper["year"] 279 | assert paper["paperId"] 280 | assert paper["citationCount"] 281 | assert paper["title"] 282 | 283 | async def test_with_multiple_google_search_pages(self) -> None: 284 | papers = await paperscraper.a_gsearch_papers( 285 | "molecular dynamics", year="2019-2023", limit=5, _limit=2 286 | ) 287 | assert len(papers) >= 5 288 | 289 | async def test_no_link_doesnt_crash_us(self) -> None: 290 | await paperscraper.a_gsearch_papers( 291 | "OAG-BERT: Pre-train Heterogeneous Entity-augmented Academic Language" 292 | " Models", 293 | year="2021", 294 | ) 295 | 296 | async def test_no_doi_doesnt_crash_us(self) -> None: 297 | await paperscraper.a_gsearch_papers( 298 | "Letters to the American People, Part II (2019–2024)", # noqa: RUF001 299 | year="2024", 300 | ) 301 | 302 | 303 | @pytest.mark.parametrize( 304 | ("title", "scraper_should_succeed"), 305 | [( 306 | "Simulation Intelligence: Towards a New Generation of Scientific Methods", 307 | "arxiv", 308 | )], 309 | ) 310 | @pytest.mark.asyncio() 311 | async def test_gsearch_examples(title, scraper_should_succeed): 312 | result = None 313 | 314 | async def status_callback(paper_title, scrape_result): 315 | # make sure most of words agree when lower 316 | t1 = set(title.lower().split()) 317 | t2 = set(paper_title.lower().split()) 318 | assert len(t1.intersection(t2)) / len(t1) > 0.5 319 | nonlocal result 320 | result = scrape_result 321 | 322 | scraper = paperscraper.default_scraper(callback=status_callback) 323 | 324 | # remove other scrapers 325 | for s in scraper.scrapers: 326 | if s.name != scraper_should_succeed: 327 | scraper.deregister_scraper(s.name) 328 | 329 | papers = await paperscraper.a_gsearch_papers(title, limit=1, scraper=scraper) 330 | assert len(papers) >= 1 331 | if result: 332 | assert scraper_should_succeed in result, "Scraper specified did not run" 333 | assert ( 334 | result[scraper_should_succeed] == "success" 335 | ), f"Scraper {scraper_should_succeed} failed" 336 | else: 337 | raise AssertionError("No result from callback") 338 | 339 | 340 | class Test1(IsolatedAsyncioTestCase): 341 | async def test_arxiv_to_pdf(self): 342 | arxiv_id = "1706.03762" 343 | path = "test.pdf" 344 | async with ThrottledClientSession( 345 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 346 | ) as session: 347 | await paperscraper.arxiv_to_pdf(arxiv_id, path, session) 348 | assert paperscraper.check_pdf(path) 349 | os.remove(path) 350 | 351 | async def test_biorxiv_to_pdf(self): 352 | biorxiv_doi = "10.1101/2024.01.25.577217" 353 | path = "test.pdf" 354 | async with ThrottledClientSession( 355 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 356 | ) as session: 357 | await paperscraper.xiv_to_pdf(biorxiv_doi, path, "www.biorxiv.org", session) 358 | assert paperscraper.check_pdf(path) 359 | os.remove(path) 360 | 361 | async def test_medrxiv_to_pdf(self): 362 | biorxiv_doi = "10.1101/2024.03.06.24303847" 363 | path = "test.pdf" 364 | async with ThrottledClientSession( 365 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 366 | ) as session: 367 | await paperscraper.xiv_to_pdf(biorxiv_doi, path, "www.medrxiv.org", session) 368 | assert paperscraper.check_pdf(path) 369 | os.remove(path) 370 | 371 | async def test_pmc_to_pdf(self) -> None: 372 | with tempfile.NamedTemporaryFile() as tmpfile: 373 | for _ in range(3): # Retrying on 403, pulling different header each retry 374 | async with ThrottledClientSession( 375 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 376 | ) as session: 377 | cause_exc: Exception | None = None 378 | try: 379 | await paperscraper.pmc_to_pdf("8971931", tmpfile.name, session) 380 | except RuntimeError as exc: 381 | cause_exc = exc 382 | else: 383 | if paperscraper.check_pdf(tmpfile.name): 384 | return 385 | raise AssertionError( 386 | "Failed to download and check PDF from PMC." 387 | ) from cause_exc 388 | 389 | def test_search_pdf_link(self) -> None: 390 | for url, expected in ( 391 | ('', None), 392 | ( 393 | 'PDF', # noqa: E501 394 | "/doi/suppl/10.1010/spam.ham.0a0/some_file/abc_001.pdf", 395 | ), 396 | ( 397 | '
file format pdf download', # noqa: E501 402 | None, 403 | ), 404 | ): 405 | if isinstance(expected, str): 406 | assert search_pdf_link(url) == expected 407 | else: 408 | try: 409 | search_pdf_link(url) 410 | except NoPDFLinkError: 411 | pass 412 | else: 413 | raise AssertionError("Should be unreachable") 414 | 415 | async def test_openaccess_scraper(self) -> None: 416 | assert not await openaccess_scraper( 417 | {"openAccessPdf": None}, MagicMock(), MagicMock() 418 | ) 419 | 420 | mock_session = MagicMock() 421 | call_index = 0 422 | 423 | @contextlib.asynccontextmanager 424 | async def mock_session_get(*_, **__): 425 | mock_response = MagicMock(spec_set=aiohttp.ClientResponse) 426 | nonlocal call_index 427 | call_index += 1 428 | if call_index == 1: 429 | mock_response.text.side_effect = [ 430 | '' # noqa: E501 431 | ] 432 | else: 433 | mock_response.headers = { 434 | "Content-Type": "application/pdf;charset=UTF-8" 435 | } 436 | mock_response.read.side_effect = [b"stub"] 437 | yield mock_response 438 | 439 | mock_session.get.side_effect = mock_session_get 440 | with tempfile.NamedTemporaryFile() as tmpfile: 441 | await openaccess_scraper( 442 | { 443 | "openAccessPdf": { 444 | "url": ( 445 | "https://pubs.acs.org/doi/abs/10.1021/acs.nanolett.0c00513" 446 | ) 447 | } 448 | }, 449 | tmpfile.name, 450 | mock_session, 451 | ) 452 | 453 | async def test_pubmed_to_pdf(self) -> None: 454 | with tempfile.NamedTemporaryFile() as tmpfile: 455 | for _ in range(3): # Retrying on 403, pulling different header each retry 456 | async with ThrottledClientSession( 457 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 458 | ) as session: 459 | cause_exc: Exception | None = None 460 | try: 461 | await paperscraper.pubmed_to_pdf( 462 | "27525504", tmpfile.name, session 463 | ) 464 | except RuntimeError as exc: 465 | cause_exc = exc 466 | else: 467 | if paperscraper.check_pdf(tmpfile.name): 468 | return 469 | raise AssertionError( 470 | "Failed to download and check PDF from PubMed ID." 471 | ) from cause_exc 472 | 473 | async def test_link_to_pdf(self): 474 | link = "https://www.aclweb.org/anthology/N18-3011.pdf" 475 | path = "test.pdf" 476 | async with ThrottledClientSession( 477 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 478 | ) as session: 479 | await paperscraper.link_to_pdf(link, path, session) 480 | assert paperscraper.check_pdf(path) 481 | os.remove(path) 482 | 483 | async def test_link2_to_pdf_that_can_raise_403(self) -> None: 484 | link = "https://journals.sagepub.com/doi/pdf/10.1177/1087057113498418" 485 | path = "test.pdf" 486 | try: 487 | async with ThrottledClientSession( 488 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 489 | ) as session: 490 | await paperscraper.link_to_pdf(link, path, session) 491 | os.remove(path) 492 | 493 | except (RuntimeError, aiohttp.ClientResponseError) as e: 494 | assert "403" in str(e) # noqa: PT017 495 | 496 | async def test_link3_to_pdf(self) -> None: 497 | with tempfile.NamedTemporaryFile() as tmpfile: 498 | for _ in range(3): # Retrying 499 | async with ThrottledClientSession( 500 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 501 | ) as session: 502 | await paperscraper.link_to_pdf( 503 | "https://www.medrxiv.org/content/medrxiv/early/2020/03/23/2020.03.20.20040055.full.pdf", 504 | tmpfile.name, 505 | session, 506 | ) 507 | if paperscraper.check_pdf(tmpfile.name): 508 | return 509 | raise AssertionError("Failed to download and check PDF from medRxiv.") 510 | 511 | async def test_chemrxivlink_to_pdf(self) -> None: 512 | with tempfile.NamedTemporaryFile() as tmpfile: 513 | async with ThrottledClientSession( 514 | headers=get_header(), rate_limit=RateLimits.FALLBACK_SLOW.value 515 | ) as session: 516 | for _ in range(3): # Retrying if invalid PDF download or 403 error 517 | with contextlib.suppress(ClientResponseError): # 403 error 518 | await paperscraper.link_to_pdf( 519 | "https://doi.org/10.26434/chemrxiv-2023-fw8n4", 520 | tmpfile.name, 521 | session, 522 | ) 523 | if paperscraper.check_pdf(tmpfile.name): 524 | return 525 | # Download completed but PDF is invalid 526 | raise AssertionError("Failed to download and check PDF from ChemRxiv.") 527 | 528 | 529 | class Test2(IsolatedAsyncioTestCase): 530 | async def test_search_papers(self): 531 | query = "molecular dynamics" 532 | papers = await paperscraper.a_search_papers(query, limit=1) 533 | assert len(papers) >= 1 534 | 535 | 536 | class Test3(IsolatedAsyncioTestCase): 537 | async def test_search_papers_offset(self): 538 | query = "molecular dynamics" 539 | papers = await paperscraper.a_search_papers(query, limit=10, _limit=5) 540 | assert len(papers) >= 10 541 | 542 | 543 | class Test4(IsolatedAsyncioTestCase): 544 | async def test_search_papers_plain(self): 545 | query = "meta-reinforcement learning meta reinforcement learning" 546 | papers = await paperscraper.a_search_papers(query, limit=3, verbose=True) 547 | assert len(papers) >= 3 548 | 549 | 550 | class Test5(IsolatedAsyncioTestCase): 551 | 552 | async def test_search_papers_year(self) -> None: 553 | query = "covid vaccination" 554 | 555 | for year, name in [ 556 | ("2019-2023", "normal range"), 557 | ("2023-2022", "flipped order"), 558 | (". 2021-2023", "discard upon bad formatting"), 559 | ]: 560 | with self.subTest(msg=name): 561 | papers = await paperscraper.a_search_papers(query, limit=1, year=year) 562 | assert len(papers) >= 1 563 | 564 | 565 | class Test6(IsolatedAsyncioTestCase): 566 | async def test_verbose(self): 567 | query = "Fungi" 568 | papers = await paperscraper.a_search_papers(query, limit=1, verbose=False) 569 | assert len(papers) >= 1 570 | 571 | 572 | class TestScraper(IsolatedAsyncioTestCase): 573 | async def test_custom_scraper(self) -> None: 574 | query = "covid vaccination" 575 | mock_scrape_fn = MagicMock() 576 | 577 | async def custom_scraper(paper, path, **kwargs): 578 | mock_scrape_fn(paper, path, **kwargs) 579 | 580 | scraper = paperscraper.Scraper() 581 | scraper.register_scraper(custom_scraper, priority=0, name="test", check=False) 582 | try: 583 | await paperscraper.a_search_papers(query, scraper=scraper) 584 | except RuntimeError as exc: 585 | assert ( # noqa: PT017 586 | exc.__cause__.status == 400 # type: ignore[union-attr] 587 | ), "Expected we should exhaust the search" 588 | 589 | async def test_scraper_callback(self) -> None: 590 | # make sure default scraper doesn't duplicate scrapers 591 | scraper = paperscraper.default_scraper() 592 | 593 | async def callback(paper, result): # noqa: ARG001 594 | assert len(result) > 5 595 | 596 | scraper.callback = callback 597 | papers = await paperscraper.a_search_papers( # noqa: F841 598 | "test", limit=1, scraper=scraper 599 | ) 600 | await scraper.close() 601 | 602 | def test_scrape_default_timeout(self) -> None: 603 | os.environ.pop("PAPERSCRAPER_SCRAPE_FUNCTION_TIMEOUT", None) 604 | assert paperscraper.Scraper.SCRAPE_FUNCTION_TIMEOUT == 60.0 605 | 606 | async def test_scraper_timeout(self) -> None: 607 | os.environ.pop("PAPERSCRAPER_SCRAPE_FUNCTION_TIMEOUT", None) 608 | os.environ["USE_IN_MEMORY_CACHE"] = "true" 609 | scraper = paperscraper.Scraper() 610 | scraper.register_scraper( 611 | openaccess_scraper, attach_session=True, rate_limit=RateLimits.SCRAPER.value 612 | ) 613 | tic = time.perf_counter() 614 | with tempfile.NamedTemporaryFile() as tmpfile: 615 | assert not await scraper.scrape( 616 | { 617 | "title": ( 618 | "Martini 3: a general purpose force field for coarse-grained" 619 | " molecular dynamics" 620 | ), 621 | "externalIds": {"DOI": "10.1038/s41592-021-01098-3"}, 622 | "openAccessPdf": { 623 | # NOTE: swapped actual for non-routable IP address to avoid CI flakiness 624 | "url": "https://10.255.255.1/test.pdf" 625 | }, 626 | }, 627 | tmpfile.name, 628 | ), "Scrape was supposed to time out" 629 | assert ( 630 | 55.0 < time.perf_counter() - tic < 65.0 631 | ), "Expected test to be about 1-min" 632 | 633 | async def test_parser_runtime_error_doesnt_crash_us(self) -> None: 634 | mock_scraper = AsyncMock(name="stub", side_effect=[True]) 635 | scraper = paperscraper.Scraper() 636 | scraper.register_scraper(mock_scraper, name="stub", check=False) 637 | with tempfile.TemporaryDirectory() as tmpdir: 638 | async with ThrottledClientSession( 639 | rate_limit=RateLimits.GOOGLE_SCHOLAR.value 640 | ) as session: 641 | assert not await scraper.batch_scrape( 642 | papers=[{ 643 | "title": ( 644 | "An essential role of active site arginine residue in" 645 | " iodide binding and histidine residue in electron" 646 | " transfer for iodide oxidation by horseradish" 647 | " peroxidase" 648 | ), 649 | "inline_links": { 650 | "serpapi_cite_link": "https://serpapi.com/search.json?engine=google_scholar_cite&hl=en&q=uWOXVY5eGm8J", 651 | }, 652 | "externalIds": {"DOI": "10.1023/A:1007154515475"}, 653 | "paperId": "stub", 654 | }], 655 | paper_file_dump_dir=tmpdir, 656 | paper_parser=partial( 657 | parse_google_scholar_metadata, session=session 658 | ), 659 | ), "Expected empty return because this test checks for parser failure" 660 | mock_scraper.assert_awaited_once() 661 | 662 | 663 | class Test8(IsolatedAsyncioTestCase): 664 | async def test_scraper_length(self): 665 | # make sure default scraper doesn't duplicate scrapers 666 | scraper = paperscraper.default_scraper() 667 | assert len(scraper.scrapers) == sum([len(s) for s in scraper.sorted_scrapers]) 668 | 669 | 670 | class Test10(IsolatedAsyncioTestCase): 671 | async def test_scraper_paper_search(self): 672 | # make sure default scraper doesn't duplicate scrapers 673 | papers = await paperscraper.a_search_papers( 674 | "649def34f8be52c8b66281af98ae884c09aef38b", 675 | limit=1, 676 | search_type="paper_recommendations", 677 | ) 678 | assert len(papers) >= 1 679 | 680 | 681 | class Test11(IsolatedAsyncioTestCase): 682 | async def test_scraper_doi_search(self): 683 | for _ in range(3): # Retrying upon unsuccessful scrape 684 | papers = await paperscraper.a_search_papers( 685 | "10.1016/j.ccell.2021.11.002", limit=1, search_type="doi" 686 | ) 687 | if len(papers) >= 1: 688 | return 689 | raise AssertionError("Failed to acquire a paper from DOI search.") 690 | 691 | 692 | class Test12(IsolatedAsyncioTestCase): 693 | async def test_future_citation_search(self): 694 | # make sure default scraper doesn't duplicate scrapers 695 | papers = await paperscraper.a_search_papers( 696 | "649def34f8be52c8b66281af98ae884c09aef38b", 697 | limit=1, 698 | search_type="future_citations", 699 | ) 700 | assert len(papers) >= 1 701 | 702 | 703 | class Test13(IsolatedAsyncioTestCase): 704 | async def test_past_references_search(self): 705 | # make sure default scraper doesn't duplicate scrapers 706 | papers = await paperscraper.a_search_papers( 707 | "649def34f8be52c8b66281af98ae884c09aef38b", 708 | limit=1, 709 | search_type="past_references", 710 | ) 711 | assert len(papers) >= 1 712 | 713 | 714 | class Test14(IsolatedAsyncioTestCase): 715 | async def test_scraper_doi_search(self): 716 | try: 717 | papers = await paperscraper.a_search_papers( # noqa: F841 718 | "10.23919/eusipco55093.2022.9909972", limit=1, search_type="doi" 719 | ) 720 | except Exception as e: 721 | assert isinstance(e, DOINotFoundError) # noqa: PT017 722 | 723 | 724 | class Test15(IsolatedAsyncioTestCase): 725 | async def test_pdf_link_from_google(self): 726 | papers = await paperscraper.a_search_papers( 727 | "Multiplex Base Editing to Protect from CD33-Directed Therapy: Implications" 728 | " for Immune and Gene Therapy", 729 | limit=1, 730 | search_type="google", 731 | ) 732 | assert len(papers) == 1 733 | 734 | 735 | class Test16(IsolatedAsyncioTestCase): 736 | def test_format_bibtex(self) -> None: 737 | bibtex = """ 738 | @['JournalArticle']{Salomón-Ferrer2013RoutineMM, 739 | author = {Romelia Salomón-Ferrer and A. Götz and D. Poole and S. Le Grand and R. Walker}, 740 | booktitle = {Journal of Chemical Theory and Computation}, 741 | journal = {Journal of chemical theory and computation}, 742 | pages = { 743 | 3878-88 744 | }, 745 | title = {Routine Microsecond Molecular Dynamics Simulations with AMBER on GPUs. 2. Explicit Solvent Particle Mesh Ewald.}, 746 | volume = {9 9}, 747 | year = {2013} 748 | } 749 | """ # noqa: E501 750 | text = "Romelia Salomón-Ferrer, A. Götz, D. Poole, S. Le Grand, and R. Walker. Routine microsecond molecular dynamics simulations with amber on gpus. 2. explicit solvent particle mesh ewald. Journal of chemical theory and computation, 9 9:3878-88, 2013." # noqa: E501 751 | assert paperscraper.format_bibtex(bibtex, "Salomón-Ferrer2013RoutineMM") == text 752 | 753 | bibtex2 = """ 754 | @['Review']{Kianfar2019ComparisonAA, 755 | author = {E. Kianfar}, 756 | booktitle = {Reviews in Inorganic Chemistry}, 757 | journal = {Reviews in Inorganic Chemistry}, 758 | pages = {157 - 177}, 759 | title = {Comparison and assessment of zeolite catalysts performance dimethyl ether and light olefins production through methanol: a review}, 760 | volume = {39}, 761 | year = {2019} 762 | } 763 | """ # noqa: E501 764 | 765 | parse_string(clean_upbibtex(bibtex2), "bibtex") 766 | 767 | bibtex3 = """ 768 | @None{Kianfar2019ComparisonAA, 769 | author = {E. Kianfar}, 770 | booktitle = {Reviews in Inorganic Chemistry}, 771 | journal = {Reviews in Inorganic Chemistry}, 772 | pages = {157 - 177}, 773 | title = {Comparison and assessment of zeolite catalysts performance dimethyl ether and light olefins production through methanol: a review}, 774 | volume = {39}, 775 | year = {2019} 776 | } 777 | """ # noqa: E501 778 | 779 | parse_string(clean_upbibtex(bibtex3), "bibtex") 780 | 781 | bibtex4 = """ 782 | @['Review', 'JournalArticle', 'Some other stuff']{Kianfar2019ComparisonAA, 783 | author = {E. Kianfar}, 784 | booktitle = {Reviews in Inorganic Chemistry}, 785 | journal = {Reviews in Inorganic Chemistry}, 786 | pages = {157 - 177}, 787 | title = {Comparison and assessment of zeolite catalysts performance dimethyl ether and light olefins production through methanol: a review}, 788 | volume = {39}, 789 | year = {2019} 790 | } 791 | """ # noqa: E501 792 | 793 | parse_string(clean_upbibtex(bibtex4), "bibtex") 794 | 795 | bibtex5 = """ 796 | @Review{Escobar2020BCGVP, 797 | author = {Luis E. Escobar and A. Molina-Cruz and C. Barillas-Mury}, 798 | title = {BCG Vaccine Protection from Severe Coronavirus Disease 2019 (COVID19)}, 799 | year = {2020} 800 | } 801 | """ 802 | 803 | parse_string(clean_upbibtex(bibtex5), "bibtex") 804 | 805 | # Edge case where there is no title or author 806 | bibtex6 = """ 807 | @article{2023, 808 | volume = {383}, 809 | ISSN = {0378-4274}, 810 | url = {http://dx.doi.org/10.1016/j.toxlet.2023.05.004}, 811 | DOI = {10.1016/j.toxlet.2023.05.004}, 812 | journal = {Toxicology Letters}, 813 | publisher = {Elsevier BV}, 814 | year = {2023}, 815 | month = jul, 816 | pages = {33–42} 817 | } 818 | """ # noqa: RUF001 819 | key: str = bibtex6.split("{")[1].split(",")[0] 820 | # Check callers can intuit this conversion's failure 821 | with contextlib.suppress(CitationConversionError): 822 | format_bibtex(bibtex6, key, clean=False) 823 | 824 | # This BibTeX apparent has a trailing slash in its title 825 | bibtex7 = r""" 826 | @article{Jain2014Antioxidant, 827 | title={Antioxidant and Antibacterial Activities of Spondias pinnata Kurz. Leaves\}, 828 | volume={4}, 829 | ISSN={2231-0894}, 830 | url={http://dx.doi.org/10.9734/ejmp/2014/7048}, 831 | DOI={10.9734/ejmp/2014/7048}, 832 | number={2}, 833 | journal={European Journal of Medicinal Plants}, 834 | publisher={Sciencedomain International}, 835 | author={Jain, Preeti}, 836 | year={2014}, 837 | month=jan, 838 | pages={183–195} 839 | } 840 | """ # noqa: RUF001 841 | assert ( 842 | "Antioxidant and Antibacterial Activities of Spondias pinnata" 843 | in format_bibtex( 844 | bibtex7, key=bibtex7.split("{")[1].split(",")[0], clean=False 845 | ) 846 | ) 847 | -------------------------------------------------------------------------------- /paperscraper/lib.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import asyncio 4 | import contextlib 5 | import logging 6 | import os 7 | import re 8 | import sys 9 | from collections.abc import Iterable 10 | from enum import Enum, IntEnum, auto 11 | from functools import partial 12 | from pathlib import Path 13 | from typing import Any 14 | 15 | from aiohttp import ClientResponse, ClientResponseError, ClientSession, InvalidURL 16 | 17 | from .exceptions import CitationConversionError, DOINotFoundError, NoPDFLinkError 18 | from .headers import get_header 19 | from .log_formatter import CustomFormatter 20 | from .scraper import Scraper 21 | from .utils import ( 22 | ThrottledClientSession, 23 | crossref_headers, 24 | encode_id, 25 | find_doi, 26 | get_scheme_hostname, 27 | search_pdf_link, 28 | ) 29 | 30 | year_extract_pattern = re.compile(r"\b\d{4}\b") 31 | 32 | 33 | def clean_upbibtex(bibtex: str) -> str: 34 | # WTF Semantic Scholar? 35 | mapping = { 36 | "None": "article", 37 | "Article": "article", 38 | "JournalArticle": "article", 39 | "Review": "article", 40 | "Book": "book", 41 | "BookSection": "inbook", 42 | "ConferencePaper": "inproceedings", 43 | "Conference": "inproceedings", 44 | "Dataset": "misc", 45 | "Dissertation": "phdthesis", 46 | "Journal": "article", 47 | "Patent": "patent", 48 | "Preprint": "article", 49 | "Report": "techreport", 50 | "Thesis": "phdthesis", 51 | "WebPage": "misc", 52 | "Plain": "article", 53 | } 54 | 55 | if "@None" in bibtex: 56 | return bibtex.replace("@None", "@article") 57 | # new format check 58 | match = re.findall(r"@\['(.*)'\]", bibtex) 59 | if len(match) == 0: 60 | match = re.findall(r"@(.*)\{", bibtex) 61 | bib_type = match[0] 62 | current = f"@{match[0]}" 63 | else: 64 | bib_type = match[0] 65 | current = f"@['{bib_type}']" 66 | for k, v in mapping.items(): 67 | # can have multiple 68 | if k in bib_type: 69 | bibtex = bibtex.replace(current, f"@{v}") 70 | break 71 | return bibtex 72 | 73 | 74 | def format_bibtex(bibtex, key, clean: bool = True) -> str: 75 | # WOWOW This is hard to use 76 | from pybtex.database import parse_string 77 | from pybtex.style.formatting import unsrtalpha 78 | from pybtex.style.template import FieldIsMissing 79 | 80 | style = unsrtalpha.Style() 81 | try: 82 | bd = parse_string(clean_upbibtex(bibtex) if clean else bibtex, "bibtex") 83 | except Exception: 84 | return "Ref " + key 85 | try: 86 | entry = style.format_entry(label="1", entry=bd.entries[key]) 87 | return entry.text.render_as("text") 88 | except (FieldIsMissing, UnicodeDecodeError): 89 | try: 90 | return bd.entries[key].fields["title"] 91 | except KeyError as exc: 92 | raise CitationConversionError( 93 | f"Failed to process{' and clean up' if clean else ''} bibtex {bibtex}" 94 | " due to missing a 'title' field." 95 | ) from exc 96 | 97 | 98 | async def likely_pdf(response: ClientResponse) -> bool: 99 | try: 100 | text = await response.text() 101 | if "Invalid article ID" in text: 102 | return False 103 | if "No paper" in text: 104 | return False 105 | except UnicodeDecodeError: 106 | return True 107 | return True 108 | 109 | 110 | async def arxiv_to_pdf(arxiv_id, path, session: ClientSession) -> None: 111 | # download 112 | async with session.get( 113 | f"https://arxiv.org/pdf/{arxiv_id}.pdf", allow_redirects=True 114 | ) as r: 115 | if not r.ok or not await likely_pdf(r): 116 | raise RuntimeError(f"No paper with arxiv id {arxiv_id}") 117 | with open(path, "wb") as f: # noqa: ASYNC101 118 | f.write(await r.read()) 119 | 120 | 121 | async def xiv_to_pdf(doi, path, domain: str, session: ClientSession) -> None: 122 | async with session.get( 123 | f"https://{domain}/content/{doi}.full.pdf", allow_redirects=True 124 | ) as r: 125 | if r.ok and await likely_pdf(r): 126 | with open(path, "wb") as f: # noqa: ASYNC101 127 | f.write(await r.read()) 128 | return 129 | 130 | 131 | async def link_to_pdf(url, path, session: ClientSession) -> None: 132 | # download 133 | async with session.get(url, allow_redirects=True) as r: 134 | r.raise_for_status() 135 | if "pdf" in r.headers["Content-Type"]: 136 | with open(path, "wb") as f: # noqa: ASYNC101 137 | f.write(await r.read()) 138 | return 139 | # try to find a pdf link 140 | html_text = await r.text() 141 | 142 | # I know this looks weird 143 | # I just need to try stuff and be able 144 | # to break out of flow if I find a pdf 145 | def get_pdf() -> str: 146 | # try for chemrxiv special tag 147 | pdf_link = re.search( 148 | r'content="(https://chemrxiv.org/engage/api-gateway/chemrxiv/assets.*\.pdf)"', 149 | html_text, 150 | ) 151 | if pdf_link: 152 | return pdf_link.group(1) 153 | try: 154 | return search_pdf_link(html_text, epdf=True) 155 | except NoPDFLinkError: 156 | return search_pdf_link(html_text) 157 | 158 | try: 159 | pdf_link = get_pdf() 160 | except NoPDFLinkError as exc: 161 | raise RuntimeError(f"No PDF link found for {url}.") from exc 162 | # check if the link is relative 163 | if pdf_link.startswith("/"): 164 | pdf_link = get_scheme_hostname(url) + pdf_link 165 | 166 | try: 167 | async with session.get(pdf_link, allow_redirects=True) as r: 168 | r.raise_for_status() 169 | if "pdf" in r.headers["Content-Type"]: 170 | with open(path, "wb") as f: # noqa: ASYNC101 171 | f.write(await r.read()) 172 | return 173 | raise RuntimeError(f"No PDF found from URL {pdf_link!r}.") 174 | except (TypeError, InvalidURL) as exc: 175 | raise RuntimeError(f"Malformed URL {pdf_link!r} from {url}.") from exc 176 | 177 | 178 | async def find_pmc_pdf_link(pmc_id, session: ClientSession) -> str: 179 | url = f"https://www.ncbi.nlm.nih.gov/pmc/articles/PMC{pmc_id}" 180 | async with session.get(url) as r: 181 | try: 182 | r.raise_for_status() 183 | except ClientResponseError as exc: 184 | raise RuntimeError( 185 | f"Failed to download PubMed Central ID {pmc_id} from URL {url}." 186 | ) from exc 187 | try: 188 | pdf_link = search_pdf_link(text=await r.text()) 189 | except NoPDFLinkError as exc: 190 | raise RuntimeError( 191 | f"No PDF link matched for PubMed Central ID {pmc_id} from URL {url}." 192 | ) from exc 193 | return f"https://www.ncbi.nlm.nih.gov{pdf_link}" 194 | 195 | 196 | async def pubmed_to_pdf(pubmed_id, path, session: ClientSession) -> None: 197 | async with session.get(f"https://pubmed.ncbi.nlm.nih.gov/{pubmed_id}/") as r: 198 | if not r.ok: 199 | raise RuntimeError( 200 | f"Error fetching PMC ID for PubMed ID {pubmed_id}. {r.status}" 201 | ) 202 | html_text = await r.text() 203 | pmc_id_match = re.search(r"PMC\d+", html_text) 204 | if pmc_id_match is None: 205 | raise RuntimeError(f"No PMC ID found for PubMed ID {pubmed_id}.") 206 | pmc_id = pmc_id_match.group(0) 207 | pmc_id = pmc_id[3:] 208 | await pmc_to_pdf(pmc_id, path, session) 209 | 210 | 211 | async def pmc_to_pdf( 212 | pmc_id: str, path: str | os.PathLike, session: ClientSession 213 | ) -> None: 214 | pdf_url = await find_pmc_pdf_link(pmc_id, session) 215 | async with session.get(pdf_url, allow_redirects=True) as r: 216 | cause_exc: Exception | None = None 217 | try: 218 | r.raise_for_status() 219 | except ClientResponseError as exc: 220 | cause_exc = exc 221 | if not await likely_pdf(r): 222 | cause_exc = ValueError("Not a PDF.") 223 | if cause_exc: 224 | raise RuntimeError( 225 | f"Failed to convert PubMed Central ID {pmc_id} to PDF given URL" 226 | f" {pdf_url}." 227 | ) from cause_exc 228 | with open(path, "wb") as f: # noqa: ASYNC101 229 | f.write(await r.read()) 230 | 231 | 232 | async def arxiv_scraper(paper, path, session: ClientSession) -> bool: 233 | # check doi 234 | # example: 10.48550/arXiv.2305.10379 235 | if "DOI" in paper["externalIds"] and paper["externalIds"]["DOI"].split("/")[ 236 | -1 237 | ].startswith("arXiv"): 238 | arxiv_id = paper["externalIds"]["DOI"].split("/arXiv.")[-1] 239 | await arxiv_to_pdf(arxiv_id, path, session) 240 | return True 241 | # check if it was somehow set 242 | if "ArXiv" in paper["externalIds"]: 243 | arxiv_id = paper["externalIds"]["ArXiv"] 244 | await arxiv_to_pdf(arxiv_id, path, session) 245 | return True 246 | return False 247 | 248 | 249 | async def xiv_scraper(paper, path, domain: str, session: ClientSession) -> bool: 250 | if "DOI" not in paper["externalIds"]: 251 | return False 252 | doi = paper["externalIds"]["DOI"] 253 | # check if it has biorxiv/medrxiv prefix 254 | if not doi.startswith("10.1101/"): 255 | return False 256 | await xiv_to_pdf(doi, path, domain, session) 257 | return True 258 | 259 | 260 | async def medrxiv_scraper(paper, path, session: ClientSession) -> bool: 261 | return await xiv_scraper(paper, path, "www.medrxiv.org", session) 262 | 263 | 264 | async def biorxiv_scraper(paper, path, session: ClientSession) -> bool: 265 | return await xiv_scraper(paper, path, "www.biorxiv.org", session) 266 | 267 | 268 | async def chemrxiv_scraper(paper, path, session: ClientSession) -> bool: 269 | if "DOI" not in paper["externalIds"]: 270 | return False 271 | doi = paper["externalIds"]["DOI"] 272 | # check if it has chemrxiv prefix 273 | if "chemrxiv" not in doi: 274 | return False 275 | # get resolved doi 276 | link = f"https://doi.org/{doi}" 277 | await link_to_pdf(link, path, session) 278 | return True 279 | 280 | 281 | async def pmc_scraper(paper, path, session: ClientSession) -> bool: 282 | if "PubMedCentral" not in paper["externalIds"]: 283 | return False 284 | pmc_id = paper["externalIds"]["PubMedCentral"] 285 | await pmc_to_pdf(pmc_id, path, session) 286 | return True 287 | 288 | 289 | async def pubmed_scraper(paper, path, session: ClientSession) -> bool: 290 | if "PubMed" not in paper["externalIds"]: 291 | return False 292 | pubmed_id = paper["externalIds"]["PubMed"] 293 | await pubmed_to_pdf(pubmed_id, path, session) 294 | return True 295 | 296 | 297 | async def openaccess_scraper(paper, path, session: ClientSession) -> bool: 298 | # NOTE: paper may not have the key 'openAccessPdf', or its value may be None 299 | url = (paper.get("openAccessPdf") or {}).get("url") 300 | if not url: 301 | return False 302 | await link_to_pdf(url, path, session) 303 | return True 304 | 305 | 306 | async def local_scraper(paper, path) -> bool: # noqa: ARG001 307 | return True 308 | 309 | 310 | def default_scraper(**scraper_kwargs) -> Scraper: 311 | scraper = Scraper(**scraper_kwargs) 312 | scraper.register_scraper(local_scraper, priority=12) 313 | scraper_rate_limit_config: dict[str, Any] = { 314 | "attach_session": True, 315 | "rate_limit": RateLimits.SCRAPER.value, 316 | } 317 | scraper.register_scraper(arxiv_scraper, **scraper_rate_limit_config) 318 | scraper.register_scraper(medrxiv_scraper, **scraper_rate_limit_config) 319 | scraper.register_scraper(biorxiv_scraper, **scraper_rate_limit_config) 320 | scraper.register_scraper(chemrxiv_scraper, **scraper_rate_limit_config) 321 | scraper.register_scraper(pmc_scraper, priority=9, **scraper_rate_limit_config) 322 | scraper.register_scraper(pubmed_scraper, priority=9, **scraper_rate_limit_config) 323 | scraper.register_scraper( 324 | openaccess_scraper, priority=9, **scraper_rate_limit_config 325 | ) 326 | return scraper 327 | 328 | 329 | async def parse_semantic_scholar_metadata(paper: dict[str, Any]) -> dict[str, Any]: 330 | """Parse raw paper metadata from Semantic Scholar into a richer format.""" 331 | bibtex = paper["citationStyles"]["bibtex"] 332 | key = bibtex.split("{")[1].split(",")[0] 333 | return { 334 | "citation": format_bibtex(bibtex, key), 335 | "key": key, 336 | "bibtex": clean_upbibtex(bibtex), 337 | "tldr": paper.get("tldr"), 338 | "year": paper["year"], 339 | "url": paper["url"], 340 | "paperId": paper["paperId"], 341 | "doi": paper["externalIds"].get("DOI"), 342 | "citationCount": paper["citationCount"], 343 | "title": paper["title"], 344 | } 345 | 346 | 347 | async def preprocess_google_scholar_metadata( # noqa: C901 348 | paper: dict[str, Any], session: ClientSession 349 | ) -> dict[str, Any]: 350 | # get years 351 | match = year_extract_pattern.findall(paper["publication_info"]["summary"]) 352 | year = match[0] if len(match) > 0 else None 353 | paper["year"] = year 354 | 355 | # set pdf link 356 | if "resources" in paper: 357 | for res in paper["resources"]: 358 | if "file_format" in res and res["file_format"] == "PDF": 359 | paper["openAccessPdf"] = {"url": res["link"]} 360 | break 361 | if "link" in res: 362 | paper["openAccessPdf"] = {"url": res["link"]} 363 | # do not break, we want to try to get a pdf link 364 | 365 | # did we get a link? If not, fallback onto given link 366 | if "openAccessPdf" not in paper and "link" in paper: 367 | paper["openAccessPdf"] = {"url": paper["link"]} 368 | 369 | # set external ids 370 | paper["externalIds"] = {} 371 | if "link" in paper: 372 | if paper["link"].startswith("https://arxiv.org/abs/"): 373 | paper["externalIds"]["ArXiv"] = paper["link"].split( 374 | "https://arxiv.org/abs/" 375 | )[1] 376 | 377 | doi = find_doi(paper["link"]) 378 | if doi is not None: 379 | paper["externalIds"]["DOI"] = doi 380 | if "DOI" not in paper["externalIds"]: 381 | # Fall back to getting DOI from crossref 382 | author_query = [] 383 | if "authors" in paper["publication_info"]: 384 | author_query = [a["name"] for a in paper["publication_info"]["authors"]] 385 | doi = await reconcile_doi(paper["title"], author_query, session) 386 | paper["externalIds"]["DOI"] = doi 387 | 388 | # set citation count 389 | paper["citationCount"] = ( 390 | int(paper["inline_links"]["cited_by"]["total"]) 391 | if ( 392 | "cited_by" in paper["inline_links"] 393 | and paper["inline_links"]["cited_by"]["total"] 394 | ) 395 | else 0 # best we can do 396 | ) 397 | 398 | # set paperId to be hex digest of doi 399 | paper["paperId"] = encode_id(doi) # type: ignore[arg-type] 400 | return paper 401 | 402 | 403 | async def parallel_preprocess_google_scholar_metadata( 404 | papers: Iterable[dict[str, Any]], 405 | session: ClientSession, 406 | logger: logging.Logger | None = None, 407 | ) -> list[dict[str, Any]]: 408 | """ 409 | Preprocess papers in parallel, discarding ones with preprocessing failures. 410 | 411 | NOTE: this function does not preserve the order of papers due to variable 412 | preprocessing times. 413 | """ 414 | preprocessed_papers = [] 415 | 416 | async def index(paper: dict[str, Any]) -> None: 417 | try: 418 | preprocessed_papers.append( 419 | await preprocess_google_scholar_metadata(paper, session) 420 | ) 421 | except DOINotFoundError: 422 | if logger: 423 | logger.exception(f"Failed to find a DOI for paper {paper}.") 424 | 425 | await asyncio.gather(*(index(p) for p in papers)) 426 | return preprocessed_papers 427 | 428 | 429 | async def parse_google_scholar_metadata( 430 | paper: dict[str, Any], session: ClientSession 431 | ) -> dict[str, Any]: 432 | """Parse pre-processed paper metadata from Google Scholar into a richer format.""" 433 | doi: str | None = (paper.get("externalIds") or {}).get("DOI") 434 | citation: str | None = None 435 | if doi: 436 | try: 437 | bibtex = await doi_to_bibtex(doi, session) 438 | key: str = bibtex.split("{")[1].split(",")[0] 439 | citation = format_bibtex(bibtex, key, clean=False) 440 | except DOINotFoundError: 441 | doi = None 442 | except CitationConversionError: 443 | citation = None 444 | if (not doi or not citation) and "inline_links" in paper: 445 | # get citation by following link 446 | # SLOW SLOW Using SerpAPI for this 447 | async with session.get( 448 | paper["inline_links"]["serpapi_cite_link"], 449 | params={"api_key": os.environ["SERPAPI_API_KEY"]}, 450 | ) as r: 451 | # we raise here, because something really is wrong. 452 | r.raise_for_status() 453 | data = await r.json() 454 | citation = next(c["snippet"] for c in data["citations"] if c["title"] == "MLA") 455 | bibtex_link = next(c["link"] for c in data["links"] if c["name"] == "BibTeX") 456 | async with session.get(bibtex_link) as r: 457 | try: 458 | r.raise_for_status() 459 | except ClientResponseError as exc: 460 | # we may have a 443 - link expired 461 | msg = ( 462 | "Google scholar blocked" 463 | if r.status == 443 # noqa: PLR2004 464 | else "Unexpected failure to follow" 465 | ) 466 | raise RuntimeError( 467 | f"{msg} bibtex link {bibtex_link} for paper {paper}." 468 | ) from exc 469 | bibtex = await r.text() 470 | if not bibtex.strip().startswith("@"): 471 | raise RuntimeError( 472 | f"Google scholar ip block bibtex link {bibtex_link} for paper" 473 | f" {paper}." 474 | ) 475 | key = bibtex.split("{")[1].split(",")[0] 476 | 477 | if not citation: 478 | raise RuntimeError( 479 | f"Exhausted all options for citation retrieval for {paper!r}" 480 | ) 481 | return { 482 | "citation": citation, 483 | "key": key, 484 | "bibtex": bibtex, 485 | "year": paper["year"], 486 | "url": paper.get("link"), 487 | "paperId": paper["paperId"], 488 | "doi": paper["externalIds"].get("DOI"), 489 | "citationCount": paper["citationCount"], 490 | "title": paper["title"], 491 | } 492 | 493 | 494 | async def reconcile_doi(title: str, authors: list[str], session: ClientSession) -> str: 495 | """ 496 | Look up a DOI given a title and author list using Crossref. 497 | 498 | Raises: 499 | DOINotFoundError: If the reconciliation fails due to (1) Crossref API call had 500 | non-'ok' status code, (2) Crossref API response status indicates failure, or 501 | (3) Crossref response's entry had a low score. 502 | """ 503 | # do not want initials 504 | authors_query = " ".join([a for a in authors if len(a) > 1]) 505 | mailto = os.environ.get("CROSSREF_MAILTO", "paperscraper@example.org") 506 | # get DOI via crossref 507 | url = "https://api.crossref.org/works" 508 | params = { 509 | "query.title": title, 510 | "mailto": mailto, 511 | "select": "DOI,score", 512 | "rows": "1", 513 | } 514 | if authors_query: 515 | params["query.author"] = authors_query 516 | async with session.get(url, params=params, headers=crossref_headers()) as r: 517 | try: 518 | r.raise_for_status() 519 | except ClientResponseError as exc: 520 | raise DOINotFoundError("Could not reconcile DOI " + title) from exc 521 | data = await r.json() 522 | if data["status"] == "failed": 523 | raise DOINotFoundError(f"Could not find DOI for {title}") 524 | if ( 525 | data["message"]["total-results"] == 0 526 | or data["message"]["items"][0]["score"] < 0.5 # noqa: PLR2004 527 | ): 528 | raise DOINotFoundError(f"Could not find DOI for {title}") 529 | return data["message"]["items"][0]["DOI"] 530 | 531 | 532 | async def doi_to_bibtex(doi: str, session: ClientSession) -> str: 533 | # get DOI via crossref 534 | url = f"https://api.crossref.org/works/{doi}/transform/application/x-bibtex" 535 | async with session.get(url, headers=crossref_headers()) as r: 536 | if not r.ok: 537 | raise DOINotFoundError( 538 | f"Per HTTP status code {r.status}, could not resolve DOI {doi}." 539 | ) 540 | data = await r.text() 541 | # must make new key 542 | key = data.split("{")[1].split(",")[0] 543 | new_key = key.replace("_", "") 544 | try: 545 | author_frag = ( 546 | data.split("author={")[1] 547 | .split("}")[0] 548 | .split()[0] 549 | .strip() 550 | .replace(" and ", "") 551 | .replace(",", "") 552 | ) 553 | title_frag = data.split("title={")[1].split("}")[0].split()[0].strip() 554 | year_frag = data.split("year={")[1].split("}")[0].split()[0].strip() 555 | except IndexError: 556 | return data.replace(key, new_key) 557 | new_key = f"{author_frag}{year_frag}{title_frag}" 558 | return data.replace(key, new_key) 559 | 560 | 561 | class RateLimits(float, Enum): 562 | """Rate limits (requests/sec) based on API provider.""" 563 | 564 | SEMANTIC_SCHOLAR = 90.0 565 | GOOGLE_SCHOLAR = 30.0 566 | # SEE: https://www.crossref.org/documentation/metadata-plus/#00343 567 | CROSSREF = 30.0 # noqa: PIE796 568 | SCRAPER = 30 / 60 569 | FALLBACK_SLOW = 15 / 60 570 | 571 | 572 | SEMANTIC_SCHOLAR_API_FIELDS: str = ",".join([ 573 | "citationStyles", 574 | "externalIds", 575 | "url", 576 | "openAccessPdf", 577 | "year", 578 | "isOpenAccess", 579 | "influentialCitationCount", 580 | "citationCount", 581 | "title", 582 | ]) 583 | SEMANTIC_SCHOLAR_BASE_URL = "https://api.semanticscholar.org" 584 | 585 | 586 | class SematicScholarSearchType(IntEnum): 587 | DEFAULT = auto() 588 | PAPER = auto() 589 | PAPER_RECOMMENDATIONS = auto() 590 | DOI = auto() 591 | FUTURE_CITATIONS = auto() 592 | PAST_REFERENCES = auto() 593 | GOOGLE = auto() 594 | 595 | def make_url_params( # noqa: PLR0911 596 | self, 597 | params: dict[str, Any], 598 | query: str, 599 | offset: int, 600 | limit: int, 601 | include_base_url: bool = True, 602 | ) -> tuple[str, dict[str, Any]]: 603 | """ 604 | Make the target URL and in-place update the input URL parameters. 605 | 606 | Args: 607 | params: URL parameters to in-place update. 608 | query: Either a search query or a Semantic Scholar paper ID. 609 | offset: Offset to place in the URL parameters for the default search type. 610 | limit: Limit to place in the URL parameters for some search types. 611 | include_base_url: Set True (default) to include the base URL. 612 | 613 | Returns: 614 | Two-tuple of URL and URL parameters. 615 | """ 616 | base = SEMANTIC_SCHOLAR_BASE_URL if include_base_url else "" 617 | if self == SematicScholarSearchType.DEFAULT: 618 | params["query"] = query.replace("-", " ") 619 | params["offset"] = offset 620 | params["limit"] = limit 621 | return f"{base}/graph/v1/paper/search", params 622 | if self == SematicScholarSearchType.PAPER: 623 | return f"{base}/graph/v1/paper/{query}", params 624 | if self == SematicScholarSearchType.PAPER_RECOMMENDATIONS: 625 | return f"{base}/recommendations/v1/papers/forpaper/{query}", params 626 | if self == SematicScholarSearchType.DOI: 627 | return f"{base}/graph/v1/paper/DOI:{query}", params 628 | if self == SematicScholarSearchType.FUTURE_CITATIONS: 629 | params["limit"] = limit 630 | return f"{base}/graph/v1/paper/{query}/citations", params 631 | if self == SematicScholarSearchType.PAST_REFERENCES: 632 | params["limit"] = limit 633 | return f"{base}/graph/v1/paper/{query}/references", params 634 | if self == SematicScholarSearchType.GOOGLE: 635 | params["limit"] = 1 636 | return f"{base}/graph/v1/paper/search", params 637 | raise NotImplementedError 638 | 639 | 640 | # The fact that 20 is actually the max value was not in the SERP API docs as 641 | # of 4/15/2024, but was determined by contacting SERP support 642 | GOOGLE_SEARCH_MAX_PAGE_SIZE = 20 643 | 644 | 645 | async def a_search_papers( # noqa: C901, PLR0912, PLR0915 646 | query: str, 647 | limit: int = 10, 648 | pdir: str | os.PathLike = os.curdir, 649 | semantic_scholar_api_key: str | None = None, 650 | _paths: dict[str | os.PathLike, dict[str, Any]] | None = None, 651 | _limit: int = 100, 652 | _offset: int = 0, 653 | logger: logging.Logger | None = None, 654 | year: str | None = None, 655 | verbose: bool = False, 656 | scraper: Scraper | None = None, 657 | batch_size: int = 10, 658 | search_type: str = "default", 659 | ) -> dict[str, dict[str, Any]]: 660 | """ 661 | Asynchronously search for papers using Semantic Scholar, and scrape them. 662 | 663 | Args: 664 | query: Search input, its exact meaning depends on the search_type. 665 | limit: Target result count, we will try to give at least this many results. 666 | However, for cases when Semantic Scholar doesn't give enough results, 667 | there will be less than this value. 668 | pdir: Optional directory (created if it does not exist), that defaults to the 669 | current directory, passed to Scraper.batch_scrape's paper_file_dump_dir. 670 | semantic_scholar_api_key: Optional Semantic Scholar API key, otherwise 671 | attempt to pull it from the environment variable SEMANTIC_SCHOLAR_API_KEY. 672 | _paths: Previous Scraper.batch_scrape, used internally for recursion. 673 | _limit: Result limit to pass to the Semantic Scholar API, only relevant for 674 | some search_type. 675 | _offset: Offset in the search results, used internally for recursion. 676 | logger: Optional logger to use for logging. If left as default of None, 677 | a 'paper-scraper' logger at ERROR level will be used. 678 | year: Optional year string, either a single year (e.g. '2019') 679 | or a year range (e.g. '2019-2023'). 680 | verbose: Set True to colorized log to stderr at DEBUG level. 681 | scraper: Optional scraper to use after searching. If left as default of None, 682 | the default scraper will be created. 683 | batch_size: Passed through to Scraper.batch_scrape's batch_size. 684 | search_type: Lowercase string corresponding with a SematicScholarSearchType key. 685 | 686 | Returns: 687 | Dict union of all Scraper.batch_scrape outputs. 688 | """ 689 | pdir = Path(pdir) 690 | pdir.mkdir(exist_ok=True) 691 | if logger is None: 692 | logger = logging.getLogger("paper-scraper") 693 | logger.setLevel(logging.ERROR) 694 | if verbose: 695 | logger.setLevel(logging.DEBUG) 696 | ch = logging.StreamHandler() 697 | ch.setFormatter(CustomFormatter()) 698 | logger.addHandler(ch) 699 | params = {"fields": SEMANTIC_SCHOLAR_API_FIELDS} 700 | if _limit > 100: # noqa: PLR2004 701 | raise NotImplementedError("Didn't handle Semantic Scholar pagination ('next').") 702 | rate_limit: float = RateLimits.FALLBACK_SLOW.value 703 | endpoint, params = SematicScholarSearchType[search_type.upper()].make_url_params( 704 | params, query, _offset, _limit 705 | ) 706 | if search_type == "google": 707 | # SEE: https://serpapi.com/google-scholar-api 708 | google_endpoint = "https://serpapi.com/search.json" 709 | google_params = { 710 | "q": query, 711 | "api_key": os.environ["SERPAPI_API_KEY"], 712 | "engine": "google_scholar", 713 | "num": GOOGLE_SEARCH_MAX_PAGE_SIZE, 714 | "start": _offset, 715 | # TODO - add offset and limit here # noqa: TD004 716 | } 717 | rate_limit = RateLimits.GOOGLE_SCHOLAR.value 718 | elif search_type == "paper": 719 | raise NotImplementedError( 720 | f"Only added 'paper' search type to {SematicScholarSearchType.__name__}," 721 | " but not yet to this function in general." 722 | ) 723 | 724 | if year is not None and search_type == "default": 725 | # need to really make sure year is correct 726 | year = year.strip() 727 | if "-" in year: 728 | # make sure start/end are valid 729 | with contextlib.suppress(ValueError): 730 | start, end = year.split("-") 731 | if int(start) <= int(end): 732 | params["year"] = year 733 | if "year" not in params: 734 | logger.warning(f"Could not parse year {year}") 735 | 736 | if year is not None and search_type == "google": 737 | # need to really make sure year is correct 738 | year = year.strip() 739 | if "-" in year: 740 | # make sure start/end are valid 741 | try: 742 | start, end = year.split("-") 743 | if int(start) <= int(end): 744 | google_params["as_ylo"] = start 745 | google_params["as_yhi"] = end 746 | except ValueError: 747 | pass 748 | else: 749 | with contextlib.suppress(ValueError): 750 | google_params["as_ylo"] = year 751 | google_params["as_yhi"] = year 752 | if "as_ylo" not in google_params: 753 | logger.warning(f"Could not parse year {year}") 754 | 755 | paths: dict[str, dict[str, Any]] = ( 756 | {str(k): v for k, v in _paths.items()} if _paths is not None else {} 757 | ) 758 | scraper = scraper or default_scraper() 759 | ssheader = get_header() 760 | if semantic_scholar_api_key is not None: 761 | ssheader["x-api-key"] = semantic_scholar_api_key 762 | rate_limit = RateLimits.SEMANTIC_SCHOLAR.value 763 | else: 764 | # check if it's in the environment 765 | with contextlib.suppress(KeyError): 766 | ssheader["x-api-key"] = os.environ["SEMANTIC_SCHOLAR_API_KEY"] 767 | rate_limit = RateLimits.SEMANTIC_SCHOLAR.value 768 | async with ThrottledClientSession( 769 | rate_limit=rate_limit, headers=ssheader 770 | ) as ss_session: 771 | async with ss_session.get( 772 | url=google_endpoint if search_type == "google" else endpoint, 773 | params=google_params if search_type == "google" else params, 774 | ) as response: 775 | try: 776 | response.raise_for_status() 777 | except ClientResponseError as exc: 778 | if response.status == 404 and search_type == "doi": # noqa: PLR2004 779 | raise DOINotFoundError(f"DOI {query} not found.") from exc 780 | raise RuntimeError( 781 | f"Error searching papers given query {query}." 782 | ) from exc 783 | data = await response.json() 784 | if search_type == "default": 785 | has_more_data = _offset + _limit < data["total"] 786 | elif search_type == "google": 787 | if "organic_results" not in data: 788 | return paths 789 | has_more_data = "pagination" in data 790 | papers = data["organic_results"] 791 | titles = [p["title"] for p in papers] 792 | years: list[str | None] = [None] * len(papers) 793 | for i, p in enumerate(papers): 794 | match = year_extract_pattern.findall(p["publication_info"]["summary"]) 795 | if len(match) > 0: 796 | years[i] = match[0] 797 | 798 | # get PDF resources 799 | google_pdf_links: list[str | None] = [None] * len(papers) 800 | for i, p in enumerate(papers): 801 | if "resources" in p: 802 | for res in p["resources"]: 803 | if res.get("file_format") == "PDF": 804 | google_pdf_links[i] = res["link"] 805 | 806 | # want this separate, since ss is rate_limit for Google 807 | async with ThrottledClientSession( 808 | rate_limit=rate_limit, headers=ssheader 809 | ) as ss_sub_session: 810 | # Now we need to reconcile with S2 API these results 811 | async def google2s2( 812 | title: str, year: str | None, pdf_link 813 | ) -> dict[str, Any] | None: 814 | local_p = params.copy() 815 | local_p["query"] = title.replace("-", " ") 816 | if year is not None: 817 | local_p["year"] = year 818 | async with ss_sub_session.get( 819 | url=endpoint, params=local_p 820 | ) as response: 821 | if not response.ok: 822 | logger.warning( 823 | "Error correlating papers from google to semantic" 824 | f" scholar: status {response.status}, reason" 825 | f" {response.reason!r}, text {await response.text()!r}." 826 | ) 827 | return None 828 | response_data = await response.json() 829 | if ( 830 | "data" not in response_data 831 | and year is not None 832 | and response_data["total"] == 0 833 | ): 834 | logger.info( 835 | f"{title} | {year} not found. Now trying without year" 836 | ) 837 | del local_p["year"] 838 | async with ss_sub_session.get( 839 | url=endpoint, params=local_p 840 | ) as resp: 841 | if not resp.ok: 842 | logger.warning( 843 | "Error correlating papers from google" 844 | " to semantic scholar (no year):" 845 | f" status {resp.status}, reason {resp.reason}," 846 | f" text {await resp.text()!r}." 847 | ) 848 | response_data = await resp.json() 849 | if "data" in response_data: 850 | if pdf_link is not None: 851 | # Google Scholar url takes precedence 852 | response_data["data"][0]["openAccessPdf"] = { 853 | "url": pdf_link 854 | } 855 | return response_data["data"][0] 856 | return None 857 | 858 | responses = await asyncio.gather(*( 859 | google2s2(t, y, p) 860 | for t, y, p in zip(titles, years, google_pdf_links, strict=True) 861 | )) 862 | data = {"data": [r for r in responses if r is not None]} 863 | data["total"] = len(data["data"]) 864 | field = "data" 865 | if search_type == "paper_recommendations": 866 | field = "recommendedPapers" 867 | elif search_type == "doi": 868 | data = {"data": [data]} 869 | if field not in data: 870 | return paths 871 | papers = data[field] 872 | if search_type == "future_citations": 873 | papers = [p["citingPaper"] for p in papers] 874 | if search_type == "past_references": 875 | papers = [p["citedPaper"] for p in papers] 876 | # resort based on influentialCitationCount - is this good? 877 | if search_type == "default": 878 | papers.sort(key=lambda x: x["influentialCitationCount"], reverse=True) 879 | if search_type in ["default", "google"]: 880 | logger.info( 881 | f"Found {data['total']} papers, analyzing {_offset} to" 882 | f" {_offset + len(papers)}" 883 | ) 884 | 885 | # batch them, since we may reach desired limit before all done 886 | paths.update( 887 | await scraper.batch_scrape( 888 | papers, 889 | paper_file_dump_dir=pdir, 890 | paper_parser=parse_semantic_scholar_metadata, 891 | batch_size=batch_size, 892 | limit=limit, 893 | logger=logger, 894 | ) 895 | ) 896 | if search_type in ["default", "google"] and len(paths) < limit and has_more_data: 897 | paths.update( 898 | await a_search_papers( 899 | query, 900 | limit=limit, 901 | pdir=pdir, 902 | _paths=paths, # type: ignore[arg-type] 903 | _limit=_limit, 904 | _offset=_offset 905 | + (GOOGLE_SEARCH_MAX_PAGE_SIZE if search_type == "google" else _limit), 906 | logger=logger, 907 | year=year, 908 | verbose=verbose, 909 | scraper=scraper, 910 | batch_size=batch_size, 911 | search_type=search_type, 912 | ) 913 | ) 914 | if _offset == 0: 915 | await scraper.close() 916 | return paths 917 | 918 | 919 | async def a_gsearch_papers( # noqa: C901 920 | query: str, 921 | limit: int = 10, 922 | pdir: str | os.PathLike = os.curdir, 923 | _paths: dict[str | os.PathLike, dict[str, Any]] | None = None, 924 | _offset: int = 0, 925 | _limit: int = GOOGLE_SEARCH_MAX_PAGE_SIZE, 926 | logger: logging.Logger | None = None, 927 | year: str | None = None, 928 | verbose: bool = False, 929 | scraper: Scraper | None = None, 930 | batch_size: int = 10, 931 | ) -> dict[str, dict[str, Any]]: 932 | pdir = Path(pdir) 933 | pdir.mkdir(exist_ok=True) 934 | if logger is None: 935 | logger = logging.getLogger("paper-scraper") 936 | logger.setLevel(logging.ERROR) 937 | if verbose: 938 | logger.setLevel(logging.DEBUG) 939 | ch = logging.StreamHandler() 940 | ch.setFormatter(CustomFormatter()) 941 | logger.addHandler(ch) 942 | # SEE: https://serpapi.com/google-scholar-api 943 | endpoint = "https://serpapi.com/search.json" 944 | # adjust _limit if limit is smaller (with margin for scraping errors) 945 | # for example, if limit is 3 we would be fine only getting 8 results 946 | # but if limit is 50, this will just return normal default _limit (20) 947 | _limit = min(_limit, limit + 5) 948 | params = { 949 | "q": query, 950 | "api_key": os.environ["SERPAPI_API_KEY"], 951 | "engine": "google_scholar", 952 | "num": _limit, 953 | "start": _offset, 954 | } 955 | 956 | if year is not None: 957 | # need to really make sure year is correct 958 | year = year.strip() 959 | if "-" in year: 960 | # make sure start/end are valid 961 | try: 962 | start, end = year.split("-") 963 | if int(start) <= int(end): 964 | params["as_ylo"] = start 965 | params["as_yhi"] = end 966 | except ValueError: 967 | pass 968 | else: 969 | with contextlib.suppress(ValueError): 970 | params["as_ylo"] = year 971 | params["as_yhi"] = year 972 | if "as_ylo" not in params: 973 | logger.warning(f"Could not parse year {year}") 974 | 975 | paths: dict[str, dict[str, Any]] = ( 976 | {str(k): v for k, v in _paths.items()} if _paths is not None else {} 977 | ) 978 | scraper = scraper or default_scraper() 979 | 980 | async with ThrottledClientSession( 981 | headers=get_header(), 982 | rate_limit=RateLimits.GOOGLE_SCHOLAR.value, # Share rate limits between gs/crossref 983 | ) as session: 984 | async with session.get( 985 | url=endpoint, 986 | params=params, 987 | ) as response: 988 | if not response.ok: 989 | raise RuntimeError( 990 | "Error searching papers:" 991 | f" {response.status} {response.reason} {await response.text()}" 992 | ) 993 | data = await response.json() 994 | 995 | if "organic_results" not in data: 996 | return paths 997 | papers = data["organic_results"] 998 | total_papers = data["search_information"].get("total_results", 1) 999 | logger.info( 1000 | f"Found {total_papers} papers, analyzing {_offset} to" 1001 | f" {_offset + len(papers)}" 1002 | ) 1003 | 1004 | # batch them, since we may reach desired limit before all done 1005 | paths.update( 1006 | await scraper.batch_scrape( 1007 | # we only process papers that have a link and a DOI 1008 | await parallel_preprocess_google_scholar_metadata( 1009 | papers, session, logger 1010 | ), 1011 | paper_file_dump_dir=pdir, 1012 | paper_parser=partial(parse_google_scholar_metadata, session=session), 1013 | batch_size=batch_size, 1014 | limit=limit, 1015 | logger=logger, 1016 | ) 1017 | ) 1018 | if len(paths) < limit and _offset + _limit < total_papers: 1019 | paths.update( 1020 | await a_gsearch_papers( 1021 | query, 1022 | limit=limit, 1023 | pdir=pdir, 1024 | _paths=paths, # type: ignore[arg-type] 1025 | _offset=_offset + limit, 1026 | _limit=_limit, 1027 | logger=logger, 1028 | year=year, 1029 | verbose=verbose, 1030 | scraper=scraper, 1031 | batch_size=batch_size, 1032 | ) 1033 | ) 1034 | await scraper.close() 1035 | return paths 1036 | 1037 | 1038 | def search_papers(*a_search_args, **a_search_kwargs): 1039 | # special case for jupyter notebooks 1040 | if "get_ipython" in globals() or "google.colab" in sys.modules: 1041 | import nest_asyncio 1042 | 1043 | nest_asyncio.apply() 1044 | try: 1045 | loop = asyncio.get_running_loop() 1046 | except RuntimeError as e: # noqa: F841 1047 | loop = asyncio.new_event_loop() 1048 | asyncio.set_event_loop(loop) 1049 | return loop.run_until_complete(a_search_papers(*a_search_args, **a_search_kwargs)) 1050 | -------------------------------------------------------------------------------- /paperscraper/headers.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import random 4 | 5 | # ruff: noqa: E501 6 | 7 | user_agents = """ 8 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/37.0.2062.94 Chrome/37.0.2062.94 Safari/537.36 9 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 10 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko 11 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 12 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9 13 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4 14 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 15 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 16 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240 17 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 18 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko 19 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 20 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko 21 | Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 22 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12 23 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 24 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0 25 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/7.1.8 Safari/537.85.17 26 | Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H143 Safari/600.1.4 27 | Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F69 Safari/600.1.4 28 | Mozilla/5.0 (Windows NT 6.1; rv:40.0) Gecko/20100101 Firefox/40.0 29 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0) 30 | Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) 31 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko 32 | Mozilla/5.0 (Windows NT 5.1; rv:40.0) Gecko/20100101 Firefox/40.0 33 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 34 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/600.6.3 (KHTML, like Gecko) Version/8.0.6 Safari/600.6.3 35 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/600.5.17 (KHTML, like Gecko) Version/8.0.5 Safari/600.5.17 36 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 37 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 38 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4 39 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko 40 | Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53 41 | Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 42 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 43 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 44 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:40.0) Gecko/20100101 Firefox/40.0 45 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0) 46 | Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 47 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 48 | Mozilla/5.0 (X11; CrOS x86_64 7077.134.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.156 Safari/537.36 49 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/7.1.7 Safari/537.85.16 50 | Mozilla/5.0 (Windows NT 6.0; rv:40.0) Gecko/20100101 Firefox/40.0 51 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:40.0) Gecko/20100101 Firefox/40.0 52 | Mozilla/5.0 (iPad; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B466 Safari/600.1.4 53 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.3.18 (KHTML, like Gecko) Version/8.0.3 Safari/600.3.18 54 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 55 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 56 | Mozilla/5.0 (Windows NT 6.1; Win64; x64; Trident/7.0; rv:11.0) like Gecko 57 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 58 | Mozilla/5.0 (iPad; CPU OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4 59 | Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 60 | Mozilla/5.0 (iPad; CPU OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12D508 Safari/600.1.4 61 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0 62 | Mozilla/5.0 (iPad; CPU OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D201 Safari/9537.53 63 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 64 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.6.3 (KHTML, like Gecko) Version/7.1.6 Safari/537.85.15 65 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.4.10 (KHTML, like Gecko) Version/8.0.4 Safari/600.4.10 66 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:40.0) Gecko/20100101 Firefox/40.0 67 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/7.0.6 Safari/537.78.2 68 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12H321 Safari/600.1.4 69 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; rv:11.0) like Gecko 70 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 71 | Mozilla/5.0 (iPad; CPU OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B410 Safari/600.1.4 72 | Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53 73 | Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 74 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; rv:11.0) like Gecko 75 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; TNJB; rv:11.0) like Gecko 76 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 77 | Mozilla/5.0 (Windows NT 6.3; ARM; Trident/7.0; Touch; rv:11.0) like Gecko 78 | Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 79 | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0 80 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MDDCJS; rv:11.0) like Gecko 81 | Mozilla/5.0 (Windows NT 6.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 82 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 83 | Mozilla/5.0 (Windows NT 6.2; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 84 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H143 Safari/600.1.4 85 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFASWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 86 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12H321 Safari/600.1.4 87 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 88 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 89 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 90 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko 91 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:40.0) Gecko/20100101 Firefox/40.0 92 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0 93 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4 94 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MATBJS; rv:11.0) like Gecko 95 | Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; KFJWI Build/IMM76D) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 96 | Mozilla/5.0 (iPad; CPU OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53 97 | Mozilla/5.0 (X11; CrOS armv7l 7077.134.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.156 Safari/537.36 98 | Mozilla/5.0 (X11; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0 99 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) 100 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25 101 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 102 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 103 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 104 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 105 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 106 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/8.0 Safari/600.1.25 107 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0 108 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56 109 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFSOWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 110 | Mozilla/5.0 (iPad; CPU OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3 111 | Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 112 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 113 | Mozilla/5.0 (iPad; CPU OS 8_1_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B435 Safari/600.1.4 114 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 115 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 116 | Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240 117 | Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 118 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; LCJB; rv:11.0) like Gecko 119 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MDDRJS; rv:11.0) like Gecko 120 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFAPWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 121 | Mozilla/5.0 (Windows NT 6.3; Trident/7.0; Touch; rv:11.0) like Gecko 122 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 123 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; LCJB; rv:11.0) like Gecko 124 | Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFOT Build/IML74K) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 125 | Mozilla/5.0 (iPad; CPU OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B329 Safari/8536.25 126 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFARWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 127 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; ASU2JS; rv:11.0) like Gecko 128 | Mozilla/5.0 (iPad; CPU OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A405 Safari/600.1.4 129 | Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) 130 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 131 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.77.4 (KHTML, like Gecko) Version/7.0.5 Safari/537.77.4 132 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 133 | Mozilla/5.0 (Windows NT 6.1; rv:38.0) Gecko/20100101 Firefox/38.0 134 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; yie11; rv:11.0) like Gecko 135 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MALNJS; rv:11.0) like Gecko 136 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/8.0.57838 Mobile/12H321 Safari/600.1.4 137 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0 138 | Mozilla/5.0 (Windows NT 10.0; rv:40.0) Gecko/20100101 Firefox/40.0 139 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MAGWJS; rv:11.0) like Gecko 140 | Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 141 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.5.17 (KHTML, like Gecko) Version/7.1.5 Safari/537.85.14 142 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 143 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; TNJB; rv:11.0) like Gecko 144 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; NP06; rv:11.0) like Gecko 145 | Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 146 | Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:40.0) Gecko/20100101 Firefox/40.0 147 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174 148 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.4.8 (KHTML, like Gecko) Version/8.0.3 Safari/600.4.8 149 | Mozilla/5.0 (iPad; CPU OS 7_0_6 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B651 Safari/9537.53 150 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 151 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.3.18 (KHTML, like Gecko) Version/7.1.3 Safari/537.85.12 152 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Web Preview) Chrome/27.0.1453 Safari/537.36 153 | Mozilla/5.0 (iPad; CPU OS 8_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A365 Safari/600.1.4 154 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 155 | Mozilla/5.0 (Windows NT 6.1; rv:39.0) Gecko/20100101 Firefox/39.0 156 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 AOL/9.7 AOLBuild/4343.4049.US Safari/537.36 157 | Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko 158 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 159 | Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12H143 Safari/600.1.4 160 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0 161 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0 162 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:39.0) Gecko/20100101 Firefox/39.0 163 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 164 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 165 | Mozilla/5.0 (iPad; CPU OS 7_0_3 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B511 Safari/9537.53 166 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10 167 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 168 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/7.1.2 Safari/537.85.11 169 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; ASU2JS; rv:11.0) like Gecko 170 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 171 | Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1 172 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 173 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0 174 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MDDCJS; rv:11.0) like Gecko 175 | Mozilla/5.0 (Windows NT 6.3; rv:40.0) Gecko/20100101 Firefox/40.0 176 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) Qt/4.8.5 Safari/534.34 177 | Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53 BingPreview/1.0b 178 | Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 179 | Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12H143 Safari/600.1.4 180 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 181 | Mozilla/5.0 (X11; CrOS x86_64 7262.52.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.86 Safari/537.36 182 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 183 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MDDCJS; rv:11.0) like Gecko 184 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 185 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 186 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.4.10 (KHTML, like Gecko) Version/7.1.4 Safari/537.85.13 187 | Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.0.0 Safari/538.1 188 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko 189 | Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12F69 Safari/600.1.4 190 | Mozilla/5.0 (Android; Tablet; rv:40.0) Gecko/40.0 Firefox/40.0 191 | Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53 192 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 193 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 194 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1 195 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 196 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 197 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFSAWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 198 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 AOL/9.8 AOLBuild/4346.13.US Safari/537.36 199 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MAAU; rv:11.0) like Gecko 200 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 201 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) 202 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 203 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 204 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36 205 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.74.9 (KHTML, like Gecko) Version/7.0.2 Safari/537.74.9 206 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 207 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 208 | Mozilla/5.0 (iPad; CPU OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53 209 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MAARJS; rv:11.0) like Gecko 210 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 211 | Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53 212 | Mozilla/5.0 (Windows NT 10.0; Trident/7.0; rv:11.0) like Gecko 213 | Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12F69 Safari/600.1.4 214 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/7.0.6 Safari/537.78.2 215 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0 216 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MASMJS; rv:11.0) like Gecko 217 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 218 | Mozilla/5.0 (Windows NT 10.0; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0 219 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174 220 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; FunWebProducts; rv:11.0) like Gecko 221 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MAARJS; rv:11.0) like Gecko 222 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; BOIE9;ENUS; rv:11.0) like Gecko 223 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T230NU Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 224 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; EIE10;ENUSWOL; rv:11.0) like Gecko 225 | Mozilla/5.0 (Windows NT 5.1; rv:39.0) Gecko/20100101 Firefox/39.0 226 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:39.0) Gecko/20100101 Firefox/39.0 227 | Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; KFJWA Build/IMM76D) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 228 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174 229 | Mozilla/5.0 (Linux; Android 4.0.4; BNTV600 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36 230 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4 231 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36 232 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 233 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; yie9; rv:11.0) like Gecko 234 | Mozilla/5.0 (Linux; Android 5.0.2; SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 235 | Mozilla/5.0 (iPad; CPU OS 9_0 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13A4325c Safari/601.1 236 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 237 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B466 Safari/600.1.4 238 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0 239 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 240 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36 241 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/7.0) 242 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0 243 | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0 244 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 245 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12D508 Safari/600.1.4 246 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 247 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/44.0.2403.67 Mobile/12H321 Safari/600.1.4 248 | Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 249 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/7.0; .NET4.0E; .NET4.0C) 250 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 251 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 252 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 253 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 254 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36 255 | Mozilla/5.0 (PlayStation 4 2.57) AppleWebKit/537.73 (KHTML, like Gecko) 256 | Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0 257 | Mozilla/5.0 (Linux; Android 5.0; SM-G900V Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 258 | Mozilla/5.0 (X11; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0 259 | Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 260 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36 261 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; LCJB; rv:11.0) like Gecko 262 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:38.0) Gecko/20100101 Firefox/38.0 263 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 264 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; Touch) 265 | Mozilla/5.0 (Linux; Android 5.0.2; SM-T800 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 266 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36 267 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MASMJS; rv:11.0) like Gecko 268 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 269 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 270 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36 271 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:39.0) Gecko/20100101 Firefox/39.0 272 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; TNJB; rv:11.0) like Gecko 273 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14 274 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36 275 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 276 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; ASJB; rv:11.0) like Gecko 277 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 278 | Mozilla/5.0 (Linux; Android 5.0.1; SAMSUNG SCH-I545 4G Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 279 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36 280 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174 281 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36 282 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; EIE10;ENUSMSN; rv:11.0) like Gecko 283 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12H321 Safari/600.1.4 284 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; MATBJS; rv:11.0) like Gecko 285 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0 286 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MASAJS; rv:11.0) like Gecko 287 | Mozilla/5.0 (Windows NT 6.1; rv:41.0) Gecko/20100101 Firefox/41.0 288 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MALC; rv:11.0) like Gecko 289 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 AOL/9.7 AOLBuild/4343.4049.US Safari/537.36 290 | Mozilla/5.0 (Windows NT 10.0; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0 291 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/33.0.0.0 Safari/534.24 292 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; MDDCJS; rv:11.0) like Gecko 293 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0 294 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E) 295 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36 296 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E) 297 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 298 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:39.0) Gecko/20100101 Firefox/39.0 299 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 300 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; yie10; rv:11.0) like Gecko 301 | Mozilla/5.0 (Linux; Android 5.0; SAMSUNG-SM-G900A Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 302 | Mozilla/5.0 (Linux; U; Android 4.0.3; en-gb; KFTT Build/IML74K) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 303 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/8.0) 304 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; TNJB; rv:11.0) like Gecko 305 | Mozilla/5.0 (X11; CrOS x86_64 7077.111.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 306 | Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36 307 | Mozilla/5.0 (Windows NT 6.1; rv:37.0) Gecko/20100101 Firefox/37.0 308 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 309 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 LBBROWSER 310 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0 311 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36 312 | Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 313 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 314 | Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0 315 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 AOL/9.8 AOLBuild/4346.18.US Safari/537.36 316 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; GWX:QUALIFIED) 317 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36 318 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MDDCJS; rv:11.0) like Gecko 319 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 AOL/9.8 AOLBuild/4346.13.US Safari/537.36 320 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 AOL/9.7 AOLBuild/4343.4043.US Safari/537.36 321 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0 322 | Mozilla/5.0 (Windows NT 5.1; rv:38.0) Gecko/20100101 Firefox/38.0 323 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.13 Safari/537.36 324 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36 325 | Mozilla/5.0 (iPad; CPU OS 6_0_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A523 Safari/8536.25 326 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MANM; rv:11.0) like Gecko 327 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.2000 Chrome/30.0.1599.101 Safari/537.36 328 | Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/8.0.57838 Mobile/12H143 Safari/600.1.4 329 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0 330 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; MDDRJS) 331 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 332 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.22 Safari/537.36 333 | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 334 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MATBJS; rv:11.0) like Gecko 335 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36 336 | Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 337 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Gecko/20100101 Firefox/37.0 338 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 AOL/9.8 AOLBuild/4346.13.US Safari/537.36 339 | Mozilla/5.0 (Windows NT 5.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 340 | Mozilla/5.0 (X11; Linux x86_64; U; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 341 | Mozilla/5.0 (X11; CrOS x86_64 6946.86.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 342 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 343 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36 344 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; TNJB; rv:11.0) like Gecko 345 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 346 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; MDDRJS; rv:11.0) like Gecko 347 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 348 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 349 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36 350 | Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/8.0.57838 Mobile/12F69 Safari/600.1.4 351 | Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D201 Safari/9537.53 352 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; GIL 3.5; rv:11.0) like Gecko 353 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:41.0) Gecko/20100101 Firefox/41.0 354 | Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LG-V410/V41010d Build/KOT49I.V41010d) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.1599.103 Safari/537.36 355 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14 356 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B411 Safari/600.1.4 357 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MATBJS; rv:11.0) like Gecko 358 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 359 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) Qt/4.8.1 Safari/534.34 360 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; USPortal; rv:11.0) like Gecko 361 | Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H143 362 | Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:40.0) Gecko/20100101 Firefox/40.0.2 Waterfox/40.0.2 363 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; SMJB; rv:11.0) like Gecko 364 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; CMDTDF; .NET4.0C; .NET4.0E) 365 | Mozilla/5.0 (iPad; CPU OS 6_1_2 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B146 Safari/8536.25 366 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 367 | Mozilla/5.0 (MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko 368 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36 369 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 370 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; TNJB; rv:11.0) like Gecko 371 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0 372 | Mozilla/5.0 (X11; FC Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0 373 | Mozilla/5.0 (X11; CrOS armv7l 7262.52.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.86 Safari/537.36 374 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MASAJS; rv:11.0) like Gecko 375 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MS-RTC LM 8; .NET4.0C; .NET4.0E) 376 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; yie11; rv:11.0) like Gecko 377 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10532 378 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; BOIE9;ENUSMSE; rv:11.0) like Gecko 379 | Mozilla/5.0 (Windows NT 6.2; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0 380 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; InfoPath.3) 381 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0 382 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3) 383 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T320 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 384 | Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/44.0.2403.67 Mobile/12H143 Safari/600.1.4 385 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 386 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12H321 Safari/600.1.4 387 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 388 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 389 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; 360SE) 390 | Mozilla/5.0 (Linux; Android 5.0.2; LG-V410/V41020c Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.1847.118 Safari/537.36 391 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36 392 | Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) GSA/7.0.55539 Mobile/11D257 Safari/9537.53 393 | Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12F69 394 | Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.13 Safari/537.36 395 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36 396 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E) 397 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFTHWA Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 398 | Mozilla/5.0 (Android; Mobile; rv:40.0) Gecko/40.0 Firefox/40.0 399 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 400 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0 401 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 AOL/9.7 AOLBuild/4343.4043.US Safari/537.36 402 | Mozilla/5.0 (Linux; Android 4.4.2; SM-P600 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 403 | Mozilla/5.0 (X11; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0 404 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36 405 | Mozilla/5.0 (Windows NT 6.1; rv:35.0) Gecko/20100101 Firefox/35.0 406 | Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25 407 | Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.22 Safari/537.36 408 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; 360SE) 409 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 410 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; LCJB; rv:11.0) like Gecko 411 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 412 | Mozilla/5.0 (X11; CrOS x86_64 6812.88.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.153 Safari/537.36 413 | Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0 414 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; ASU2JS; rv:11.0) like Gecko 415 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36 416 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 417 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.13 Safari/537.36 418 | Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 419 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) 420 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/537.16 (KHTML, like Gecko) Version/8.0 Safari/537.16 421 | Mozilla/5.0 (Windows NT 6.1; rv:34.0) Gecko/20100101 Firefox/34.0 422 | Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-N900V 4G Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 423 | Mozilla/5.0 (Linux; Android 4.4.3; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.81 like Chrome/44.0.2403.128 Safari/537.36 424 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; CMDTDF; .NET4.0C; .NET4.0E; GWX:QUALIFIED) 425 | Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/11D257 Safari/9537.53 426 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0 427 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.1000 Chrome/30.0.1599.101 Safari/537.36 428 | Mozilla/5.0 (Linux; Android 4.4.2; GT-P5210 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 429 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36 430 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 431 | Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 432 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MDDSJS; rv:11.0) like Gecko 433 | Mozilla/5.0 (Linux; Android 4.4.2; QTAQZ3 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 434 | Mozilla/5.0 (Linux; Android 4.4.2; QMV7B Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 435 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 436 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MATBJS; rv:11.0) like Gecko 437 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/6.0.51363 Mobile/12H321 Safari/600.1.4 438 | Mozilla/5.0 (iPad; CPU OS 8_1_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B436 Safari/600.1.4 439 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36 440 | Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1 441 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 442 | Mozilla/5.0 (Linux; U; Android 4.0.3; en-ca; KFTT Build/IML74K) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 443 | Mozilla/5.0 (Windows NT 5.1; rv:30.0) Gecko/20100101 Firefox/30.0 444 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 445 | Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:40.0) Gecko/20100101 Firefox/40.0.2 Waterfox/40.0.2 446 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:38.0) Gecko/20100101 Firefox/38.0 447 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; LCJB; rv:11.0) like Gecko 448 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; NISSC; rv:11.0) like Gecko 449 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36 450 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 451 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 452 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71 453 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 454 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; MALC; rv:11.0) like Gecko 455 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 456 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 457 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.0.9895 Safari/537.36 458 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MSBrowserIE; rv:11.0) like Gecko 459 | Mozilla/5.0 (Linux; Android 5.0.1; SAMSUNG SM-N910V 4G Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 460 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36 461 | Mozilla/5.0 (Windows NT 6.2; rv:40.0) Gecko/20100101 Firefox/40.0 462 | Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Safari/537.36 463 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36 464 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36 465 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 466 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; LCJB; rv:11.0) like Gecko 467 | Mozilla/5.0 (Windows NT 6.0; rv:39.0) Gecko/20100101 Firefox/39.0 468 | Mozilla/5.0 (Linux; Android 5.0.2; SM-T700 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 469 | Mozilla/5.0 (Linux; Android 5.0.1; SAMSUNG-SM-N910A Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 470 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; ASU2JS; rv:11.0) like Gecko 471 | Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0 472 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0 473 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0 474 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 475 | Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 (.NET CLR 3.5.30729) 476 | Mozilla/5.0 (X11; CrOS x86_64 7077.95.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.90 Safari/537.36 477 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.1000 Chrome/30.0.1599.101 Safari/537.36 478 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 479 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 LBBROWSER 480 | Mozilla/5.0 (Windows NT 6.1; rv:36.0) Gecko/20100101 Firefox/36.0 481 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 482 | Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0) 483 | Mozilla/5.0 (iPad; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12B466 Safari/600.1.4 484 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 485 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Win64; x64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727) 486 | Mozilla/5.0 (Linux; Android 5.0.2; VK810 4G Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 487 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.76.4 (KHTML, like Gecko) Version/7.0.4 Safari/537.76.4 488 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 489 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:40.0) Gecko/20100101 Firefox/40.0 490 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 491 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; SMJB; rv:11.0) like Gecko 492 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; MDDCJS; rv:11.0) like Gecko 493 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36 494 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; BOIE9;ENUS; rv:11.0) like Gecko 495 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0 496 | Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/6.0.51363 Mobile/12H143 Safari/600.1.4 497 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:38.0) Gecko/20100101 Firefox/38.0 498 | Mozilla/5.0 (Windows NT 5.1; rv:41.0) Gecko/20100101 Firefox/41.0 499 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3) 500 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36 501 | Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2503.0 Safari/537.36 502 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.50 (KHTML, like Gecko) Version/9.0 Safari/601.1.50 503 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; GWX:RESERVED) 504 | Mozilla/5.0 (iPad; CPU OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B141 Safari/8536.25 505 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56 506 | Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 507 | Mozilla/5.0 (iPad; CPU OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12B440 Safari/600.1.4 508 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 509 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) MsnBot-Media /1.0b 510 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/7.0) 511 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 512 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.3; WOW64; Trident/7.0) 513 | Mozilla/5.0 (Linux; Android 5.1.1; SM-G920V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 514 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; ASU2JS; rv:11.0) like Gecko 515 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 516 | Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 AOL/9.7 AOLBuild/4343.4049.US Safari/537.36 517 | Mozilla/5.0 (X11; CrOS x86_64 6680.78.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.102 Safari/537.36 518 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T520 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 519 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Safari/537.36 520 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.2000 Chrome/30.0.1599.101 Safari/537.36 521 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 522 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36 523 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; MAARJS; rv:11.0) like Gecko 524 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 525 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MALNJS; rv:11.0) like Gecko 526 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T900 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 527 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 528 | Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US) 529 | Mozilla/5.0 (Windows NT 6.2; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0 530 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36 531 | Mozilla/5.0 (iPad; CPU OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12D508 Safari/600.1.4 532 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:36.0) Gecko/20100101 Firefox/36.0 533 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2503.0 Safari/537.36 534 | Mozilla/5.0 (Linux; Android 4.1.2; GT-N8013 Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 535 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFAPWA Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 536 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 537 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3) 538 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:38.0) Gecko/20100101 Firefox/38.0 539 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MALCJS; rv:11.0) like Gecko 540 | Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0 541 | Mozilla/5.0 (Linux; Android 5.0.1; SM-N910V Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 542 | Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36 543 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B436 Safari/600.1.4 544 | Mozilla/5.0 (iPad; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12B466 Safari/600.1.4 545 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A405 Safari/600.1.4 546 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Safari/537.36 547 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) 548 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:37.0) Gecko/20100101 Firefox/37.0 549 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T310 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 550 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.45 Safari/537.36 551 | Mozilla/5.0 (Linux; Android 5.1.1; Nexus 10 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 552 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36 553 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; TNJB; rv:11.0) like Gecko 554 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36 555 | Mozilla/5.0 (X11; CrOS x86_64 7077.123.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 556 | Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E) 557 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; 360SE) 558 | Mozilla/5.0 (Linux; Android 4.4.2; QMV7A Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 559 | Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53 560 | Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 561 | Mozilla/5.0 (Linux; Android 5.0; SAMSUNG-SM-N900A Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 562 | Mozilla/5.0 (Linux; Android 4.4.4; XT1080 Build/SU6-7.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 563 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MAARJS; rv:11.0) like Gecko 564 | Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/6.0.51363 Mobile/12F69 Safari/600.1.4 565 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; MALNJS; rv:11.0) like Gecko 566 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.2000 Chrome/30.0.1599.101 Safari/537.36 567 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; ASJB; rv:11.0) like Gecko 568 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11 569 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/7.0; TNJB; 1ButtonTaskbar) 570 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 571 | Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like Gecko 572 | Mozilla/5.0 (iPad; CPU OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3 573 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) Gecko/20100101 Firefox/35.0 574 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36 575 | Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-N910P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 576 | Mozilla/5.0 (Windows NT 6.1; rv:33.0) Gecko/20100101 Firefox/33.0 577 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 [Pinterest/iOS] 578 | Mozilla/5.0 (Linux; Android 5.0.1; LGLK430 Build/LRX21Y) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/38.0.2125.102 Safari/537.36 579 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 Safari 580 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/8.0; 1ButtonTaskbar) 581 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 582 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; NP08; NP08; MAAU; rv:11.0) like Gecko 583 | Mozilla/5.0 (Windows NT 5.1; rv:37.0) Gecko/20100101 Firefox/37.0 584 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T217S Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 585 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; EIE10;ENUSMSE; rv:11.0) like Gecko 586 | Mozilla/5.0 (Windows NT 6.2; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0 587 | Mozilla/5.0 (Windows NT 5.1; rv:35.0) Gecko/20100101 Firefox/35.0 588 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36 589 | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:37.0) Gecko/20100101 Firefox/37.0 590 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.76 Safari/537.36 591 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 LBBROWSER 592 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 593 | Mozilla/5.0 (Linux; Android 5.1; XT1254 Build/SU3TL-39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 594 | Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.13 Safari/537.36 595 | Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko 596 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36 597 | Mozilla/5.0 (iPad; CPU OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12B440 Safari/600.1.4 598 | Mozilla/5.0 (MSIE 10.0; Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko 599 | Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/44.0.2403.67 Mobile/12F69 Safari/600.1.4 600 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174 601 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 602 | Mozilla/5.0 (Linux; Android 5.0.1; SAMSUNG-SGH-I337 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 603 | Mozilla/5.0 (Linux; Android 4.4.3; KFASWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.81 like Chrome/44.0.2403.128 Safari/537.36 604 | Mozilla/5.0 (X11; CrOS armv7l 7077.111.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 605 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36 606 | Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A403 Safari/8536.25 607 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36 608 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0 609 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 610 | Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T800 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.0 Chrome/38.0.2125.102 Safari/537.36 611 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 612 | Mozilla/5.0 (Linux; Android 5.0; SM-G900V Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36 613 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MAGWJS; rv:11.0) like Gecko 614 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 615 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko 616 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 617 | Mozilla/5.0 (Windows NT 10.0; Win64; x64; Trident/7.0; rv:11.0) like Gecko 618 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; ATT-IE11; rv:11.0) like Gecko 619 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 620 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.103 Safari/537.36 621 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174 622 | Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 623 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0 624 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7) AppleWebKit/534.48.3 (KHTML, like Gecko) Version/5.1 Safari/534.48.3 625 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729) 626 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.13 Safari/537.36 627 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36 628 | Mozilla/5.0 (Windows NT 6.1; rv:32.0) Gecko/20100101 Firefox/32.0 629 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/8.0.57838 Mobile/12H321 Safari/600.1.4 630 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 631 | Mozilla/5.0 (iPad; CPU OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12D508 Safari/600.1.4 632 | Mozilla/5.0 (iPhone; CPU iPhone OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53 633 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0; MSN 9.0;MSN 9.1;MSN 9.6;MSN 10.0;MSN 10.2;MSN 10.5;MSN 11;MSN 11.5; MSNbMSNI; MSNmen-us; MSNcOTH) like Gecko 634 | Mozilla/5.0 (Windows NT 5.1; rv:36.0) Gecko/20100101 Firefox/36.0 635 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.0.9895 Safari/537.36 636 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/7.0; 1ButtonTaskbar) 637 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.102 Safari/537.36 638 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 YaBrowser/15.7.2357.2877 Safari/537.36 639 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0 640 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; BOIE9;ENUSMSNIP; rv:11.0) like Gecko 641 | Mozilla/5.0 AppleWebKit/999.0 (KHTML, like Gecko) Chrome/99.0 Safari/999.0 642 | Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0 643 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) 644 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.0.0 Safari/538.1 645 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; MAGWJS; rv:11.0) like Gecko 646 | Mozilla/5.0 (Linux; Android 4.4.2; GT-N5110 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 647 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 648 | Mozilla/5.0 (iPad; CPU OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12B410 Safari/600.1.4 649 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.7) Gecko/20150824 Firefox/31.9 PaleMoon/25.7.0 650 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Firefox/31.0 651 | Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:39.0) Gecko/20100101 Firefox/39.0 652 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 653 | Mozilla/5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13A4325c Safari/601.1 654 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 655 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; MS-RTC LM 8; InfoPath.3) 656 | Mozilla/5.0 (Linux; Android 4.4.2; RCT6203W46 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36 657 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36 658 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 659 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:31.0) Gecko/20100101 Firefox/31.0 660 | Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 661 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 662 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0) 663 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; EIE10;ENUSWOL; rv:11.0) like Gecko 664 | Mozilla/5.0 (Linux; Android 4.4.4; en-us; SAMSUNG SM-N910T Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/2.0 Chrome/34.0.1847.76 Mobile Safari/537.36 665 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 666 | Mozilla/5.0 (Linux; Android 4.4.2; RCT6203W46 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 667 | Mozilla/5.0 (Linux; U; Android 4.0.4; en-ca; KFJWI Build/IMM76D) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 668 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/34.0.1847.116 Chrome/34.0.1847.116 Safari/537.36 669 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 670 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.22 Safari/537.36 671 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36 672 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.45 Safari/537.36 673 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 674 | Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0 675 | Mozilla/5.0 (Linux; Android 4.4.2; RCT6773W22 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 676 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; ASJB; ASJB; MAAU; rv:11.0) like Gecko 677 | Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10 678 | Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.7) Gecko/20150824 Firefox/31.9 PaleMoon/25.7.0 679 | Mozilla/5.0 (Linux; Android 5.0; SAMSUNG-SM-G870A Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 680 | Mozilla/5.0 (Linux; Android 4.4.3; KFSOWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.81 like Chrome/44.0.2403.128 Safari/537.36 681 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.2) 682 | Mozilla/5.0 (Windows NT 5.2; rv:40.0) Gecko/20100101 Firefox/40.0 683 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.0.9895 Safari/537.36 684 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 AOL/9.7 AOLBuild/4343.4049.US Safari/537.36 685 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; EIE10;ENUSMCM; rv:11.0) like Gecko 686 | Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G920P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Mobile Safari/537.36 687 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36 688 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36 689 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 690 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) 691 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0 692 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MALCJS; rv:11.0) like Gecko 693 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 694 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 695 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 696 | Mozilla/5.0 (Windows NT 5.2; rv:29.0) Gecko/20100101 Firefox/29.0 /29.0 697 | Mozilla/5.0 (Linux; Android 5.0.2; SM-T550 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 698 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 AOL/9.7 AOLBuild/4343.4049.US Safari/537.36 699 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0 700 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E) 701 | Mozilla/5.0 (Linux; U; Android 4.0.3; en-gb; KFOT Build/IML74K) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 702 | Mozilla/5.0 (Linux; Android 5.0.2; SM-P900 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 703 | Mozilla/5.0 (Linux; Android 5.1.1; Nexus 9 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 704 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T530NU Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 705 | Mozilla/5.0 (X11; Linux i686; rv:40.0) Gecko/20100101 Firefox/40.0 706 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 707 | Mozilla/5.0 (Linux; Android 5.1.1; SM-T330NU Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 708 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.7.1000 Chrome/30.0.1599.101 Safari/537.36 709 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:34.0) Gecko/20100101 Firefox/34.0 710 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 711 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 712 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 713 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36 714 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 715 | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0 716 | Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.22 Safari/537.36 717 | Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1 718 | Mozilla/5.0 (Android; Tablet; rv:34.0) Gecko/34.0 Firefox/34.0 719 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MALCJS; rv:11.0) like Gecko 720 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) 721 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E) 722 | Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) GSA/8.0.57838 Mobile/11D257 Safari/9537.53 723 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36 724 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; yie10; rv:11.0) like Gecko 725 | Mozilla/5.0 (Linux; Ubuntu 14.04) AppleWebKit/537.36 Chromium/35.0.1870.2 Safari/537.36 726 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; yie11; rv:11.0) like Gecko 727 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 SE 2.X MetaSr 1.0 728 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 729 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0 730 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/8.0; TNJB; 1ButtonTaskbar) 731 | Mozilla/5.0 (Linux; Android 4.4.2; RCT6773W22 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36 732 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E) 733 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 734 | Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2503.0 Safari/537.36 735 | Mozilla/5.0 (Linux; Android 5.0; SAMSUNG-SM-G900A Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 736 | Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 (.NET CLR 3.5.30729) 737 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) 738 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36 739 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.7.1000 Chrome/30.0.1599.101 Safari/537.36 740 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; NP08; rv:11.0) like Gecko 741 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 742 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T210R Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 743 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:40.0) Gecko/20100101 Firefox/40.0.2 Waterfox/40.0.2 744 | Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-N900P Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 745 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 AOL/9.8 AOLBuild/4346.18.US Safari/537.36 746 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.22 Safari/537.36 747 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 748 | Mozilla/5.0 (Linux; Android 5.0.2; SM-T350 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 749 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; ASU2JS; rv:11.0) like Gecko 750 | Mozilla/5.0 (Linux; Android 5.0.2; SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Safari/537.36 751 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 752 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/7.0; 1ButtonTaskbar) 753 | Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG-SM-G920A Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.0 Chrome/38.0.2125.102 Mobile Safari/537.36 754 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2503.0 Safari/537.36 755 | Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; 360SE) 756 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MAAU; MAAU; rv:11.0) like Gecko 757 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 758 | Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.1 759 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MANM; MANM; rv:11.0) like Gecko 760 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36 761 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:37.0) Gecko/20100101 Firefox/37.0 762 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b 763 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36 764 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36 765 | Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 AOL/9.7 AOLBuild/4343.4049.US Safari/537.36 766 | Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0 767 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36 768 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 769 | Mozilla/5.0 (Linux; Android 4.4.2; QTAQZ3 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36 770 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 OverDrive Media Console/3.3.1 771 | Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Mobile/11D257 772 | Mozilla/5.0 (iPad; CPU OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) GSA/7.0.55539 Mobile/11D201 Safari/9537.53 773 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 774 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 775 | Mozilla/5.0 (Linux; Android 5.0.1; SCH-I545 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 776 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 777 | Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 778 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A365 Safari/600.1.4 779 | Mozilla/5.0 (Windows NT 5.1; rv:34.0) Gecko/20100101 Firefox/34.0 780 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0 781 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MDDCJS; rv:11.0) like Gecko 782 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 783 | Mozilla/5.0 (iPad;U;CPU OS 5_1_1 like Mac OS X; zh-cn)AppleWebKit/534.46.0(KHTML, like Gecko)CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3 784 | Mozilla/5.0 (Linux; Android 4.4.3; KFAPWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.81 like Chrome/44.0.2403.128 Safari/537.36 785 | Mozilla/5.0 (iPad; CPU OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/11D201 Safari/9537.53 786 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 787 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 788 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36 789 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/43.0.2357.61 Mobile/12H321 Safari/600.1.4 790 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MAMIJS; rv:11.0) like Gecko 791 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36 792 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36 793 | Mozilla/5.0 (Linux; Android 5.0.1; VS985 4G Build/LRX21Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 794 | Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0 795 | Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 796 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/45.0.2454.68 Mobile/12H143 Safari/600.1.4 797 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 798 | Mozilla/5.0 (Windows NT 6.0; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0 799 | Mozilla/5.0 (Linux; Android 5.0.2; LG-V410/V41020b Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.1847.118 Safari/537.36 800 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2503.0 Safari/537.36 801 | Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 802 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B435 Safari/600.1.4 803 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 804 | Mozilla/5.0 (X11; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0 805 | Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 806 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:36.0) Gecko/20100101 Firefox/36.0 807 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; InfoPath.3; .NET4.0C; .NET4.0E) 808 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 809 | Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 810 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36 811 | Mozilla/5.0 (Windows NT 5.2; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 812 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MDDRJS; rv:11.0) like Gecko 813 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.2000 Chrome/30.0.1599.101 Safari/537.36 814 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.3; WOW64; Trident/6.0) 815 | Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Mobile Safari/537.36 816 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; MS-RTC LM 8) 817 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2503.0 Safari/537.36 818 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36 819 | Mozilla/5.0 (Linux; Android 4.4.3; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.0.0 Safari/537.36 820 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 821 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 822 | Mozilla/5.0 (Linux; Android 4.4.3; KFSAWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.81 like Chrome/44.0.2403.128 Safari/537.36 823 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 824 | Mozilla/5.0 (Windows NT 5.1; rv:32.0) Gecko/20100101 Firefox/32.0 825 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T230NU Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Safari/537.36 826 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 827 | Mozilla/5.0 (Linux; Android 4.2.2; SM-T110 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 828 | Mozilla/5.0 (Linux; Android 5.0.1; SAMSUNG SM-N910T Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 829 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E) 830 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 831 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Win64; x64; Trident/7.0) 832 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:33.0) Gecko/20100101 Firefox/33.0 833 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 834 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36 835 | Mozilla/5.0 (Windows NT 6.2; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 836 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36 837 | Mozilla/5.0 (X11; CrOS armv7l 6946.86.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 838 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36 839 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35 840 | http://www.useragentstring.com/Firefox25.0_id_19710.php 841 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T330NU Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 842 | Mozilla/5.0 (iPad; CPU OS 6_0_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A8426 Safari/8536.25 843 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 844 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 845 | Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 846 | Mozilla/5.0 (Linux; Android 5.0.2; LG-V410 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 847 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 TheWorld 6 848 | Mozilla/5.0 (iPad; CPU OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12B410 Safari/600.1.4 849 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 850 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36 851 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0 Safari/600.1.25 852 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; EIE10;ENUSWOL) 853 | Mozilla/5.0 (iPad; CPU OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/43.0.2357.61 Mobile/12H143 Safari/600.1.4 854 | Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/43.0.2357.61 Mobile/12F69 Safari/600.1.4 855 | Mozilla/5.0 (Linux; Android 4.4.2; SM-T237P Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 856 | Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36 857 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; ATT; rv:11.0) like Gecko 858 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36 859 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 860 | Mozilla/5.0 (Linux; Android 5.0.2; SM-T800 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Safari/537.36 861 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; EIE10;ENUSMSN; rv:11.0) like Gecko 862 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; MATBJS; rv:11.0) like Gecko 863 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36 864 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 865 | Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.1599.103 Mobile Safari/537.36 866 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36 867 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36 868 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; EIE11;ENUSMSN; rv:11.0) like Gecko 869 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 870 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.1000 Chrome/30.0.1599.101 Safari/537.36 871 | Mozilla/5.0 (Windows NT 6.1; rv:29.0) Gecko/20100101 Firefox/29.0 872 | Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT 873 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36 874 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; yie8; rv:11.0) like Gecko 875 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-gb; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 876 | Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 877 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; FunWebProducts; rv:11.0) like Gecko 878 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2505.0 Safari/537.36 879 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko 880 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; BOIE9;ENUSSEM; rv:11.0) like Gecko 881 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0; Touch; WebView/1.0) 882 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 883 | Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3 884 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 885 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:33.0) Gecko/20100101 Firefox/33.0 886 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 887 | Mozilla/5.0 (Linux; Android 5.0.1; SAMSUNG SPH-L720 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 888 | Mozilla/5.0 (Windows NT 6.1; Trident/7.0; yie9; rv:11.0) like Gecko 889 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 890 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36 891 | Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFSAWA Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 892 | Mozilla/5.0 (Windows NT 10.0; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0 893 | Mozilla/5.0 (compatible; Windows NT 6.1; Catchpoint) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36 894 | Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0 895 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:32.0) Gecko/20100101 Firefox/32.0 896 | Mozilla/5.0 (Windows NT 6.0; rv:38.0) Gecko/20100101 Firefox/38.0 897 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 898 | Mozilla/5.0 (Linux; Android 4.4.4; Z970 Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36 899 | Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36 900 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10 901 | Mozilla/5.0 (X11; CrOS armv7l 6812.88.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.153 Safari/537.36 902 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36 903 | Mozilla/5.0 (iPhone; CPU iPhone OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B329 Safari/8536.25 904 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MAARJS; rv:11.0) like Gecko 905 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:36.0) Gecko/20100101 Firefox/36.0 906 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 907 | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0 908 | Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; ) 909 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 910 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; MASAJS; rv:11.0) like Gecko 911 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MAARJS; rv:11.0) like Gecko 912 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36 913 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36 914 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2 915 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0 916 | Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 917 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 SE 2.X MetaSr 1.0 918 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 BIDUBrowser/7.6 Safari/537.36 919 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 920 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MASMJS; rv:11.0) like Gecko 921 | Mozilla/5.0 (Windows NT 10.0; Trident/7.0; Touch; rv:11.0) like Gecko 922 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E; 360SE) 923 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; InfoPath.3; .NET4.0C; .NET4.0E; MS-RTC LM 8) 924 | Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MAGWJS; rv:11.0) like Gecko 925 | Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G925T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Mobile Safari/537.36 926 | Mozilla/5.0 (X11; CrOS x86_64 6457.107.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36 927 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; 360SE) 928 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4.17.9 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3 929 | Mozilla/5.0 (Linux; Android 4.2.2; GT-P5113 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 930 | Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0 DejaClick/2.5.0.11 931 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER 932 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0 933 | Mozilla/5.0 (Linux; Android 4.4.3; KFARWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.81 like Chrome/44.0.2403.128 Safari/537.36 934 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 935 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36 936 | Mozilla/5.0 (iPad; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/8.0.57838 Mobile/12B466 Safari/600.1.4 937 | Mozilla/5.0 (Unknown; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/534.34 938 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; NP08; MAAU; NP08; rv:11.0) like Gecko 939 | Mozilla/5.0 (Linux; Android 4.4.2; LG-V410 Build/KOT49I.V41010d) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 940 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0 941 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3) 942 | Mozilla/5.0 (Windows NT 6.1; rv:28.0) Gecko/20100101 Firefox/28.0 943 | Mozilla/5.0 (X11; CrOS x86_64 6946.70.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36 944 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 945 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E) 946 | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:33.0) Gecko/20100101 Firefox/33.0 947 | Mozilla/5.0 (iPod touch; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4 948 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 IceDragon/38.0.5 Firefox/38.0.5 949 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 950 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; managedpc; rv:11.0) like Gecko 951 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36 952 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MASMJS; rv:11.0) like Gecko 953 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36 954 | Mozilla/5.0 (Linux; U; Android 4.0.3; en-ca; KFOT Build/IML74K) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.68 like Chrome/39.0.2171.93 Safari/537.36 955 | Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 956 | Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) GSA/6.0.51363 Mobile/11D257 Safari/9537.53 957 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 LBBROWSER 958 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:37.0) Gecko/20100101 Firefox/37.0 959 | Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; Lumia 1520) like Gecko 960 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36 961 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0 962 | Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_6 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B651 Safari/9537.53 963 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E) 964 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E; 360SE) 965 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.103 Safari/537.36 966 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36 967 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E) 968 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:34.0) Gecko/20100101 Firefox/34.0 969 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36 970 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.87 Safari/537.36 971 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; PRU_IE; rv:11.0) like Gecko 972 | Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/37.0.2062.120 Chrome/37.0.2062.120 Safari/537.36 973 | Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 [FBAN/FBIOS;FBAV/38.0.0.6.79;FBBV/14316658;FBDV/iPad4,1;FBMD/iPad;FBSN/iPhone OS;FBSV/8.4.1;FBSS/2; FBCR/;FBID/tablet;FBLC/en_US;FBOP/1] 974 | Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174 975 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; NP02; rv:11.0) like Gecko 976 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36 977 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64; x64; Trident/4.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) 978 | Mozilla/5.0 (X11; CrOS x86_64 6946.63.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 979 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:37.0) Gecko/20100101 Firefox/37.0 980 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36 981 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.0.9895 Safari/537.36 982 | Mozilla/5.0 (Linux; Android 4.4.4; Nexus 7 Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36 983 | Mozilla/5.0 (Linux; Android 4.2.2; QMV7B Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Safari/537.36 984 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; MASMJS; rv:11.0) like Gecko 985 | Mozilla/5.0 (compatible; MSIE 10.0; AOL 9.7; AOLBuild 4343.1028; Windows NT 6.1; WOW64; Trident/7.0) 986 | Mozilla/5.0 (Linux; U; Android 4.0.3; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36 987 | Mozilla/5.0 (Windows NT 6.3; Trident/7.0; Touch; TNJB; rv:11.0) like Gecko 988 | Mozilla/5.0 (iPad; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12B466 989 | Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; Active Content Browser) 990 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E) 991 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36 992 | Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 993 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3) 994 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36 995 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0; WebView/1.0) 996 | Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36 997 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 998 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36 999 | Mozilla/5.0 (iPad; U; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3 1000 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 1001 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 1002 | Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) coc_coc_browser/50.0.125 Chrome/44.0.2403.125 Safari/537.36 1003 | Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E) 1004 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 1005 | Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; MAARJS; rv:11.0) like Gecko 1006 | Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-N900T Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36 1007 | Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/7.0.55539 Mobile/12H143 Safari/600.1.4 1008 | """ 1009 | 1010 | 1011 | def get_user_agent() -> str: 1012 | return random.choice(user_agents.splitlines()) 1013 | 1014 | 1015 | def get_header() -> dict[str, str]: 1016 | return {"User-Agent": get_user_agent()} 1017 | --------------------------------------------------------------------------------