├── __init__.py ├── test ├── __init__.py ├── config.toml └── test_confighandler.py ├── http_request_randomizer ├── requests │ ├── errors │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-37.pyc │ │ │ ├── ParserExceptions.cpython-37.pyc │ │ │ └── ProxyListException.cpython-37.pyc │ │ ├── ProxyListException.py │ │ └── ParserExceptions.py │ ├── parsers │ │ ├── __init__.py │ │ ├── js │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ │ ├── UnPacker.cpython-37.pyc │ │ │ │ └── __init__.cpython-37.pyc │ │ │ └── UnPacker.py │ │ ├── __pycache__ │ │ │ ├── UrlParser.cpython-37.pyc │ │ │ ├── __init__.cpython-37.pyc │ │ │ ├── SslProxyParser.cpython-37.pyc │ │ │ ├── FreeProxyParser.cpython-37.pyc │ │ │ ├── PremProxyParser.cpython-37.pyc │ │ │ ├── ProxyForEuParser.cpython-37.pyc │ │ │ └── RebroWeeblyParser.cpython-37.pyc │ │ ├── UrlParser.py │ │ ├── ProxyForEuParser.py │ │ ├── SslProxyParser.py │ │ ├── FreeProxyParser.py │ │ ├── RebroWeeblyParser.py │ │ └── PremProxyParser.py │ ├── runners │ │ ├── __init__.py │ │ └── proxyList.py │ ├── useragent │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-37.pyc │ │ │ └── userAgent.cpython-37.pyc │ │ └── userAgent.py │ ├── __init__.py │ ├── proxy │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-37.pyc │ │ │ ├── ProxyObject.cpython-37.pyc │ │ │ └── requestProxy.cpython-37.pyc │ │ ├── ProxyObject.py │ │ └── requestProxy.py │ ├── __pycache__ │ │ └── __init__.cpython-37.pyc │ └── data │ │ └── user_agents.txt ├── __pycache__ │ └── __init__.cpython-37.pyc └── __init__.py ├── .isort.cfg ├── .github └── FUNDING.yml ├── assets └── icon.jpg ├── .gitignore ├── requirements.txt ├── LICENSE ├── Apple Stock Notifier.spec ├── interface.py ├── config.toml ├── utils.py ├── app.py ├── confighandler.py ├── README.md ├── monitor.py ├── remote.py └── store_checker.py /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/errors/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/runners/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/js/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/useragent/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.isort.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | line_length=120 3 | known_third_party=isort 4 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'pgaref' 2 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/proxy/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'pgaref' 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [fjwillemsen] 4 | -------------------------------------------------------------------------------- /assets/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/assets/icon.jpg -------------------------------------------------------------------------------- /http_request_randomizer/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/proxy/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/proxy/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/errors/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/errors/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/__pycache__/UrlParser.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/__pycache__/UrlParser.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/proxy/__pycache__/ProxyObject.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/proxy/__pycache__/ProxyObject.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/js/__pycache__/UnPacker.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/js/__pycache__/UnPacker.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/js/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/js/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/proxy/__pycache__/requestProxy.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/proxy/__pycache__/requestProxy.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/useragent/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/useragent/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/useragent/__pycache__/userAgent.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/useragent/__pycache__/userAgent.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/__pycache__/SslProxyParser.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/__pycache__/SslProxyParser.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/errors/__pycache__/ParserExceptions.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/errors/__pycache__/ParserExceptions.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/__pycache__/FreeProxyParser.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/__pycache__/FreeProxyParser.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/__pycache__/PremProxyParser.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/__pycache__/PremProxyParser.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/__pycache__/ProxyForEuParser.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/__pycache__/ProxyForEuParser.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/errors/__pycache__/ProxyListException.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/errors/__pycache__/ProxyListException.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/__pycache__/RebroWeeblyParser.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fjwillemsen/Apple-Store-Stock-Notifier/HEAD/http_request_randomizer/requests/parsers/__pycache__/RebroWeeblyParser.cpython-37.pyc -------------------------------------------------------------------------------- /http_request_randomizer/requests/errors/ProxyListException.py: -------------------------------------------------------------------------------- 1 | class ProxyListException(Exception): 2 | def __init___(self, extraArguments): 3 | Exception.__init__(self, " was raised - {0}".format(extraArguments)) 4 | self.dErrorArguments = extraArguments -------------------------------------------------------------------------------- /http_request_randomizer/requests/errors/ParserExceptions.py: -------------------------------------------------------------------------------- 1 | class ParserException(Exception): 2 | def __init___(self, extraArguments): 3 | Exception.__init__(self, " was raised with arguments {0}".format(extraArguments)) 4 | self.dErrorArguments = extraArguments 5 | -------------------------------------------------------------------------------- /http_request_randomizer/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'pgaref' 2 | 3 | __version__ = '1.3.2' 4 | 5 | __title__ = 'http_request_randomizer' 6 | __description__ = 'A package using public proxies to randomise http requests' 7 | __uri__ = 'http://pgaref.com/blog/python-proxy' 8 | 9 | __author__ = 'Panagiotis Garefalakis' 10 | __email__ = 'pangaref@gmail.com' 11 | 12 | __license__ = 'MIT' 13 | __copyright__ = 'Copyright (c) 2020 ' + __author__ 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bot.session 2 | .vscode/* 3 | __pycache__ 4 | http_request_randomizer/ 5 | *.session 6 | config.json 7 | parameters.py 8 | data*.csv 9 | build 10 | dist 11 | plots 12 | 13 | # macOS 14 | 15 | # General 16 | .DS_Store 17 | .AppleDouble 18 | .LSOverride 19 | 20 | # Icon must end with two \r 21 | Icon 22 | 23 | # Thumbnails 24 | ._* 25 | 26 | # Files that might appear in the root of a volume 27 | .DocumentRevisions-V100 28 | .fseventsd 29 | .Spotlight-V100 30 | .TemporaryItems 31 | .Trashes 32 | .VolumeIcon.icns 33 | .com.apple.timemachine.donotpresent 34 | 35 | # Directories potentially created on remote AFP share 36 | .AppleDB 37 | .AppleDesktop 38 | Network Trash Folder 39 | Temporary Items 40 | .apdisk 41 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | appdirs>=1.4.4 2 | attrs>=20.2.0 3 | autopep8>=1.5.4 4 | black>=19.3b0 5 | certifi>=2020.6.20 6 | chardet>=3.0.4 7 | click>=7.1.2 8 | colorama>=0.4.3 9 | crayons>=0.4.0 10 | idna>=2.10 11 | isort>=5.5.4 12 | minibar>=0.5.0 13 | matplotlib>=3.4.3 14 | numpy>=1.21.3 15 | pandas>=1.3.4 16 | pep8>=1.7.1 17 | pipupgrade>=1.7.4 18 | pycodestyle>=2.6.0 19 | requests>=2.24.0 20 | toml>=0.10.1 21 | urllib3>=1.25.11 22 | telebot>=0.0.4 23 | telethon>=1.23.0 24 | 25 | # http request randomizer requirements 26 | beautifulsoup4 >= 4.9.3 27 | coverage >= 5.3 28 | httmock >= 1.3.0 29 | psutil >= 5.7.2 30 | pytest >= 6.1.1 31 | pytest-cov >= 2.10.1 32 | python-dateutil >= 2.8.1 33 | pyOpenSSL >= 19.1.0 34 | fake-useragent >= 0.1.11 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Floris-Jan Willemsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Apple Stock Notifier.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | 3 | 4 | a = Analysis( 5 | ['main.py'], 6 | pathex=[], 7 | binaries=[], 8 | datas=[('/Users/fjwillemsen/.pyenv/versions/Apple-Store-Stock-Notifier/lib/python3.11/site-packages/nicegui', 'nicegui')], 9 | hiddenimports=[], 10 | hookspath=[], 11 | hooksconfig={}, 12 | runtime_hooks=[], 13 | excludes=[], 14 | noarchive=False, 15 | optimize=0, 16 | ) 17 | pyz = PYZ(a.pure) 18 | 19 | exe = EXE( 20 | pyz, 21 | a.scripts, 22 | [], 23 | exclude_binaries=True, 24 | name='Apple Stock Notifier', 25 | debug=False, 26 | bootloader_ignore_signals=False, 27 | strip=False, 28 | upx=True, 29 | console=False, 30 | disable_windowed_traceback=False, 31 | argv_emulation=False, 32 | target_arch=None, 33 | codesign_identity=None, 34 | entitlements_file=None, 35 | ) 36 | coll = COLLECT( 37 | exe, 38 | a.binaries, 39 | a.datas, 40 | strip=False, 41 | upx=True, 42 | upx_exclude=[], 43 | name='Apple Stock Notifier', 44 | ) 45 | app = BUNDLE( 46 | coll, 47 | name='Apple Stock Notifier.app', 48 | icon=None, 49 | bundle_identifier=None, 50 | ) 51 | -------------------------------------------------------------------------------- /test/config.toml: -------------------------------------------------------------------------------- 1 | # Modify this configuration file directly when using the CLI, or via the menu on the left in the GUI app 2 | 3 | [search] 4 | device_family = "iphone_16_pro" # the device family 5 | models = ["MYM93LL/A", "MYMD3LL/A"] # the device types 6 | carriers = ["UNLOCKED/US"] # the carriers, if applicable 7 | country_code = "us" # the country code 8 | zip_code = "94061" # the zip-code area, can be left empty to use specific stores 9 | stores = [ 10 | "R044", 11 | "R089", 12 | ] # specific stores to search, can be left empty when using zip-code 13 | 14 | [general] 15 | polling_interval_seconds = 120 # recommended to make it > 10 seconds to account for processing time, make it > 30 when using random proxies 16 | report_after_n_counts = 30 # after how many times a report should be generated 17 | data_path = "data.csv" 18 | log_path = "log.txt" 19 | randomize_proxies = false 20 | 21 | [telegram] 22 | username = "" # Your Telegram username (messages will be sent to this user) 23 | api_id = "" # Telegram bot API ID (usually an 8-digit number) 24 | api_hash = "" # Telegram bot API hash 25 | bot_token = "" # Telegram bot token 26 | session_name = "" # A unique name to create the virtual telegram client 27 | -------------------------------------------------------------------------------- /interface.py: -------------------------------------------------------------------------------- 1 | """File containing interface abstract classes.""" 2 | 3 | from abc import ABC, abstractmethod 4 | from pathlib import Path 5 | 6 | 7 | class CallbacksAbstract(ABC): 8 | """An abstract class to provide an interface for callbacks from the monitor to a client.""" 9 | 10 | @abstractmethod 11 | async def on_start(self): 12 | pass 13 | 14 | @abstractmethod 15 | async def on_stop(self): 16 | pass 17 | 18 | @abstractmethod 19 | async def on_stock_available(self, message): 20 | pass 21 | 22 | @abstractmethod 23 | async def on_appointment_available(self, message): 24 | pass 25 | 26 | @abstractmethod 27 | async def on_newly_available(self): 28 | pass 29 | 30 | @abstractmethod 31 | async def on_auto_report(self, report: str): 32 | pass 33 | 34 | @abstractmethod 35 | async def on_proxy_depletion(self, message: str): 36 | pass 37 | 38 | @abstractmethod 39 | async def on_long_processing_warning(self, warning: str): 40 | pass 41 | 42 | @abstractmethod 43 | async def on_connection_error(self, error: str): 44 | pass 45 | 46 | @abstractmethod 47 | async def on_error(self, error: str, logfile_path: Path): 48 | pass 49 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | # Modify this configuration file directly when using the CLI, or via the menu on the left in the GUI app 2 | 3 | [search] 4 | device_family = "iphone_16_pro" # the device family 5 | models = ["MYM93LL/A", "MYMD3LL/A"] # the device types 6 | carriers = ["UNLOCKED/US"] # the carriers, if applicable 7 | country_code = "us" # the country code 8 | zip_code = "94061" # the zip-code area, can be left empty to use specific stores 9 | stores = [] # store-codes to search, can be left empty when using zip-code 10 | 11 | [general] 12 | polling_interval_seconds = 120 # recommended to make it > 10 seconds to account for processing time, make it > 30 when using random proxies 13 | report_after_n_counts = 30 # after how many times a report should be generated 14 | data_path = "data.csv" 15 | log_path = "log.txt" 16 | randomize_proxies = false 17 | 18 | [telegram] 19 | username = "" # Your Telegram username (messages will be sent to this user) 20 | api_id = "" # Telegram bot API ID (usually an 8-digit number) 21 | api_hash = "" # Telegram bot API hash 22 | bot_token = "" # Telegram bot token 23 | session_name = "iPhone16ProFinder" # A unique name to create the virtual telegram client 24 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | """ Utilities file, these are functions that are supposed to be very low-level, not requiring either the StoreChecker or Monitor object references """ 2 | 3 | import socket 4 | from math import floor 5 | 6 | 7 | def reboot_pi(): 8 | """Reboot the Pi""" 9 | print("Rebooting at the request of the user") 10 | import subprocess 11 | 12 | subprocess.Popen(["sudo", "reboot"]) 13 | 14 | 15 | def get_ip(): 16 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 17 | try: 18 | # doesn't even have to be reachable 19 | s.connect(("10.255.255.255", 1)) 20 | IP = s.getsockname()[0] 21 | except Exception: 22 | IP = "127.0.0.1" 23 | finally: 24 | s.close() 25 | return IP 26 | 27 | 28 | def past_time_formatter(count, polling_interval_seconds): 29 | past_seconds = count * polling_interval_seconds 30 | whole_hours = floor(past_seconds / (60 * 60)) 31 | whole_minutes = floor(past_seconds / 60) - whole_hours * 60 32 | remaining_seconds = past_seconds % 60 33 | txt = "" 34 | if whole_hours > 0: 35 | txt += f"{whole_hours} hour{'s' if whole_hours > 1 else ''} " 36 | if whole_minutes > 0: 37 | txt += f"{whole_minutes} minute{'s' if whole_minutes > 1 else ''} " 38 | if remaining_seconds > 0: 39 | txt += f"{remaining_seconds} second{'s' if remaining_seconds > 1 else ''} " 40 | txt = txt[:-1] 41 | return txt 42 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/js/UnPacker.py: -------------------------------------------------------------------------------- 1 | import re 2 | import requests 3 | import logging 4 | 5 | logger = logging.getLogger(__name__) 6 | 7 | 8 | class JsUnPacker(object): 9 | """ 10 | It takes the javascript file's url which contains the port numbers for 11 | the encrypted strings. The file has to be unpacked to a readable form just like 12 | http://matthewfl.com/unPacker.html does. Then we create a dictionary for 13 | every key:port pair. 14 | """ 15 | # TODO: it might not be necessary to unpack the js code 16 | 17 | def __init__(self, js_file_url): 18 | logger.info("JS UnPacker init path: {}".format(js_file_url)) 19 | r = requests.get(js_file_url) 20 | encrypted = r.text.strip() 21 | encrypted = '(' + encrypted.split('}(')[1][:-1] 22 | unpacked = eval('self.unpack' +encrypted) # string of the js code in unpacked form 23 | matches = re.findall(r".*?\('\.([a-zA-Z0-9]{1,6})'\).*?\((\d+)\)", unpacked) 24 | self.ports = dict((key, port) for key, port in matches) 25 | logger.debug('portmap: '+str(self.ports)) 26 | 27 | def baseN(self, num, b, numerals="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"): 28 | return ((num == 0) and numerals[0]) or (self.baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b]) 29 | 30 | def unpack(self, p, a, c, k, e=None, d=None): 31 | while c: 32 | c -= 1 33 | if k[c]: 34 | p = re.sub("\\b" + self.baseN(c, a) + "\\b", k[c], p) 35 | return p 36 | 37 | def get_port(self, key): 38 | return self.ports[key] 39 | 40 | def get_ports(self): 41 | return self.ports 42 | -------------------------------------------------------------------------------- /test/test_confighandler.py: -------------------------------------------------------------------------------- 1 | from confighandler import ConfigHandler 2 | import pytest 3 | import asyncio 4 | import nest_asyncio 5 | 6 | nest_asyncio.apply() 7 | 8 | CONFIGFILE_PATH = "./test/config.toml" 9 | 10 | 11 | def test_read(): 12 | """Test whether the confighandler correctly reads from disk.""" 13 | ch = ConfigHandler(CONFIGFILE_PATH) 14 | assert ch.get(["search", "device_family"]) == "iphone_16_pro" 15 | assert len(ch.get(["search", "stores"])) == 2 16 | 17 | 18 | def test_write(): 19 | """Test whether the confighandler correctly writes to disk.""" 20 | ch = ConfigHandler(CONFIGFILE_PATH) 21 | ch_new = ConfigHandler(CONFIGFILE_PATH) 22 | ch_new.set(["search", "device_family"], "iphone_15_pro") 23 | assert ch.get(["search", "device_family"]) == "iphone_16_pro" 24 | assert ch_new.get(["search", "device_family"]) == "iphone_15_pro" 25 | assert ch.get([]) != ch_new.get([]) 26 | ch_newest = ConfigHandler(CONFIGFILE_PATH) 27 | ch_newest.set(["search", "device_family"], "iphone_16_pro") 28 | assert ch_newest.get(["search", "device_family"]) == "iphone_16_pro" 29 | assert ch.get([]) == ch_newest.get([]) 30 | 31 | 32 | @pytest.mark.asyncio 33 | async def test_watch_changes_callback(): 34 | """Test whether the confighandler is able to watch for on-disk changes.""" 35 | 36 | def callbackfn(): 37 | raise TabError 38 | 39 | ch = ConfigHandler(CONFIGFILE_PATH) 40 | ch_new = ConfigHandler(CONFIGFILE_PATH) 41 | # check that the callback works by raising an exception 42 | with pytest.raises(TabError): 43 | task = asyncio.create_task(ch.watch_changes(callbackfn)) 44 | await asyncio.sleep(0.5) # just to make sure the file watcher is setup 45 | ch_new.set(["search", "device_family"], "iphone_15_pro") 46 | await task # can be done because we know callbacks raise an exception, otherwise use e.g. await asyncio.sleep(1) 47 | 48 | # check that the original confighandler now has the new data 49 | assert ch.get(["search", "device_family"]) == "iphone_15_pro" 50 | # restore to original for next test 51 | ch_new.set(["search", "device_family"], "iphone_16_pro") 52 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/UrlParser.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from http_request_randomizer.requests.errors.ParserExceptions import ParserException 4 | 5 | __author__ = 'pgaref' 6 | 7 | 8 | class UrlParser(object): 9 | """ 10 | An abstract class representing any URL containing Proxy information 11 | To add an extra Proxy URL just implement this class and provide a 'url specific' parse_proxyList method 12 | 13 | Attributes: 14 | :param id: A unique provider identifier 15 | :param web_url: A provider url (hhtp) 16 | :param bandwidthKBs: minimum bandwidth in KBs (to avoid straggling proxies when having the extra info from proxy provider) 17 | """ 18 | 19 | def __init__(self, id, web_url, bandwidth_KBs=None, timeout=None): 20 | self.id = id 21 | self.url = web_url 22 | self.timeout = timeout 23 | if bandwidth_KBs is not None: 24 | self.minimum_bandwidth_in_KBs = bandwidth_KBs 25 | else: 26 | self.minimum_bandwidth_in_KBs = 150 27 | 28 | def get_id(self): 29 | return self.id 30 | 31 | def get_url(self): 32 | if self.url is None: 33 | raise ParserException("webURL is NONE") 34 | return self.url 35 | 36 | def get_min_bandwidth(self): 37 | if self.minimum_bandwidth_in_KBs < 0: 38 | raise ParserException("invalid minimum bandwidth limit {0} ".format(self.minimum_bandwidth_in_KBs)) 39 | return self.minimum_bandwidth_in_KBs 40 | 41 | def parse_proxyList(self): 42 | raise ParserException(" abstract method should be implemented by each subclass") 43 | 44 | def __str__(self): 45 | return "URL Parser of '{0}' with required bandwidth: '{1}' KBs" \ 46 | .format(self.url, self.minimum_bandwidth_in_KBs) 47 | 48 | @staticmethod 49 | def valid_ip(address): 50 | """Return ``True`` if the the given *IP* is a *valid* IPv4 address 51 | 52 | :param address: ip address 53 | :type address: string 54 | :rtype: bool 55 | 56 | """ 57 | try: 58 | host_bytes = address.split('.') 59 | valid = [int(b) for b in host_bytes] 60 | valid = [b for b in valid if b >= 0 and b <= 255] 61 | return len(host_bytes) == 4 and len(valid) == 4 62 | except: 63 | return False 64 | 65 | @staticmethod 66 | def valid_ip_port(address): 67 | """Return ``True`` if the the given *Port* is a *valid* IPv4 port 68 | 69 | :param address: ip address 70 | :type address: string 71 | :rtype: bool 72 | 73 | """ 74 | match = re.findall(r'[0-9]+(?:\.[0-9]+){3}:[0-9]+', address) 75 | # hostIP = re.compile("\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}") 76 | if not match: 77 | return False 78 | return True 79 | 80 | @staticmethod 81 | def valid_port(port): 82 | return 1 <= int(port) <= 65535 83 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/useragent/userAgent.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | from fake_useragent import FakeUserAgent 4 | import logging 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | 9 | class UserAgentManager: 10 | def __init__(self, fallback=None, file=None): 11 | self.agent_file = file 12 | if file is not None: 13 | logger.info('Using local file for user agents: '+self.agent_file) 14 | self.useragents = self.load_user_agents(self.agent_file) 15 | else: 16 | logger.info('Using fake-useragent package for user agents.') 17 | if fallback is None: 18 | fallback = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36' 19 | self.fakeuseragent = FakeUserAgent(fallback=fallback, cache=False) 20 | 21 | def load_user_agents(self, useragentsfile): 22 | """ 23 | useragentsfile : string 24 | path to text file of user agents, one per line 25 | """ 26 | useragents = [] 27 | with open(useragentsfile, 'rb') as uaf: 28 | for ua in uaf.readlines(): 29 | if ua: 30 | useragents.append(ua.strip()[1:-1 - 1]) 31 | return useragents 32 | 33 | def get_random_user_agent(self): 34 | if self.agent_file: 35 | user_agent = random.choice(self.useragents) 36 | return user_agent.decode('utf-8') 37 | else: 38 | return self.fakeuseragent.random 39 | 40 | def get_first_user_agent(self): 41 | if self.agent_file: 42 | return self.useragents[0].decode('utf-8') 43 | else: 44 | logger.warning('Fake-useragent library does not support operaration get_first - change to user-agent file!') 45 | return None 46 | 47 | def get_last_user_agent(self): 48 | if self.agent_file: 49 | return self.useragents[-1].decode('utf-8') 50 | else: 51 | logger.warning('Fake-useragent library does not support operaration get_last - change to user-agent file!') 52 | return None 53 | 54 | def get_len_user_agent(self): 55 | if self.agent_file: 56 | return len(self.useragents) 57 | else: 58 | logger.warning('Fake-useragent library does not support operaration get_len - change to user-agent file!') 59 | return None 60 | 61 | 62 | if __name__ == '__main__': 63 | ua = UserAgentManager() 64 | if ua.agent_file: 65 | print("Number of User Agent headers: {0}".format(ua.get_len_user_agent())) 66 | print("First User Agent in file: {0}".format(ua.get_first_user_agent())) 67 | print("Last User Agent in file: {0}".format(ua.get_last_user_agent())) 68 | else: 69 | print("Using up-to-date user agents from online databse.") 70 | print("If you want one random header for a request, you may use the following header:\n") 71 | print("User-Agent: " + ua.get_random_user_agent() + "\n") 72 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/proxy/ProxyObject.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class ProxyObject(object): 5 | def __init__(self, source, ip, port, anonymity_level, country=None, protocols=[], tunnel=False): 6 | """ Proxy object implementation - base for all the parsing logic 7 | 8 | :param source: The name of the proxy list from which the proxy was collected 9 | :param ip: The IP address of the proxy 10 | :param port: The port number of the proxy 11 | :param anonymity_level: The anonymity level of the proxy. Can be any of :AnonymityLevel 12 | :param country: Alpha-2 country code of the country in which the proxy is geo-located 13 | :param protocols: A list of protocols that the proxy supports. May contain one or more of {HTTP, HTTPS, SOCKS5, SOCKS6} 14 | :param tunnel: Whether or not the proxy supports tunneling to HTTPS target URLs. 15 | """ 16 | self.source = source 17 | self.ip = ip 18 | self.port = port 19 | self.anonymity_level = anonymity_level 20 | self.country = country 21 | self.protocols = protocols 22 | self.tunnel = tunnel 23 | 24 | def get_address(self): 25 | return "{0}:{1}".format(self.ip, self.port) 26 | 27 | def __str__(self): 28 | """ Method is heavily used for Logging - make sure we have a readable output 29 | 30 | :return: The address representation of the proxy 31 | """ 32 | return "{0} | {1}".format(self.get_address(), self.source) 33 | 34 | def to_str(self): 35 | return "Address: {0} | Src: {1} | | Country: {2} | Anonymity: {3} | Protoc: {4} | Tunnel: {5}"\ 36 | .format(self.get_address(), self.source, self.country, self.anonymity_level, self.protocols, 37 | self.tunnel) 38 | 39 | 40 | # class AnonymityEnumMeta(EnumMeta): 41 | # def __call__(cls, value, *args, **kw): 42 | # if isinstance(value, str): 43 | # # map string Alias to enum values, defaults to Unknown 44 | # value = { 45 | # 'transparent': 1, 46 | # 'transparent proxy': 1, 47 | # 'LOW': 1, 48 | # 'anonymous': 2, 49 | # 'anonymous proxy': 2, 50 | # 'high-anonymous': 2, 51 | # 'elite': 3, 52 | # 'elite proxy': 3, 53 | # 'HIGH': 3 54 | # }.get(value, 0) 55 | # return super(AnonymityEnumMeta, cls).__call__(value, *args, **kw) 56 | 57 | 58 | class AnonymityLevel(Enum): 59 | # __metaclass__ = AnonymityEnumMeta 60 | """ 61 | UNKNOWN: The proxy anonymity capabilities are not exposed 62 | TRANSPARENT: The proxy does not hide the requester's IP address. 63 | ANONYMOUS: The proxy hides the requester's IP address, but adds headers to the forwarded request that make it clear 64 | that the request was made using a proxy. 65 | ELITE: The proxy hides the requester's IP address and does not add any proxy-related headers to the request. 66 | """ 67 | UNKNOWN = 0 # default 68 | TRANSPARENT = 1, 'transparent', 'transparent proxy', 'LOW' 69 | ANONYMOUS = 2, 'anonymous', 'anonymous proxy', 'high-anonymous' 70 | ELITE = 3, 'elite', 'elite proxy', 'HIGH', 'Elite & Anonymous' 71 | 72 | def __new__(cls, int_value, *value_aliases): 73 | obj = object.__new__(cls) 74 | obj._value_ = int_value 75 | for alias in value_aliases: 76 | cls._value2member_map_[alias] = obj 77 | return obj 78 | 79 | @classmethod 80 | def get(cls, name): 81 | try: 82 | return cls(name) 83 | except ValueError: 84 | return cls.UNKNOWN 85 | 86 | class Protocol(Enum): 87 | UNKNOWN = 0 88 | HTTP = 1 89 | HTTPS = 2 90 | SOCS4 = 3 91 | SOCS5 = 4 92 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/ProxyForEuParser.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import requests 4 | from bs4 import BeautifulSoup 5 | 6 | from http_request_randomizer.requests.parsers.UrlParser import UrlParser 7 | from http_request_randomizer.requests.proxy.ProxyObject import ProxyObject, AnonymityLevel 8 | 9 | logger = logging.getLogger(__name__) 10 | __author__ = 'pgaref' 11 | 12 | 13 | class ProxyForEuParser(UrlParser): 14 | def __init__(self, id, web_url, bandwidth=None, timeout=None): 15 | UrlParser.__init__(self, id=id, web_url=web_url, bandwidth_KBs=bandwidth, timeout=timeout) 16 | 17 | def parse_proxyList(self): 18 | curr_proxy_list = [] 19 | try: 20 | response = requests.get(self.get_url(), timeout=self.timeout) 21 | 22 | if not response.ok: 23 | logger.warning("Proxy Provider url failed: {}".format(self.get_url())) 24 | return [] 25 | 26 | content = response.content 27 | soup = BeautifulSoup(content, "html.parser") 28 | table = soup.find("table", attrs={"class": "proxy_list"}) 29 | 30 | # The first tr contains the field names. 31 | headings = [th.get_text() for th in table.find("tr").find_all("th")] 32 | 33 | datasets = [] 34 | for row in table.find_all("tr")[1:]: 35 | dataset = zip(headings, (td.get_text() for td in row.find_all("td"))) 36 | datasets.append(dataset) 37 | 38 | for dataset in datasets: 39 | # Avoid Straggler proxies and make sure it is a Valid Proxy Address 40 | proxy_obj = self.create_proxy_object(dataset) 41 | if proxy_obj is not None and UrlParser.valid_ip_port(proxy_obj.get_address()): 42 | curr_proxy_list.append(proxy_obj) 43 | else: 44 | logger.debug("Proxy Invalid: {}".format(dataset)) 45 | except AttributeError as e: 46 | logger.error("Provider {0} failed with Attribute error: {1}".format(self.id, e)) 47 | except KeyError as e: 48 | logger.error("Provider {0} failed with Key error: {1}".format(self.id, e)) 49 | except Exception as e: 50 | logger.error("Provider {0} failed with Unknown error: {1}".format(self.id, e)) 51 | finally: 52 | return curr_proxy_list 53 | 54 | def create_proxy_object(self, dataset): 55 | ip = "" 56 | port = None 57 | anonymity = AnonymityLevel.UNKNOWN 58 | country = None 59 | # Check Field[0] for tags and field[1] for values! 60 | for field in dataset: 61 | # Discard slow proxies! Speed is in KB/s 62 | if field[0] == 'Speed': 63 | if float(field[1]) < self.get_min_bandwidth(): 64 | logger.debug("Proxy with low bandwidth: {}".format(float(field[1]))) 65 | return None 66 | if field[0] == 'IP': 67 | ip = field[1].strip() # String strip() 68 | # Make sure it is a Valid IP 69 | if not UrlParser.valid_ip(ip): 70 | logger.debug("IP with Invalid format: {}".format(ip)) 71 | return None 72 | elif field[0] == 'Port': 73 | port = field[1].strip() # String strip() 74 | elif field[0] == 'Anon': 75 | anonymity = AnonymityLevel.get(field[1].strip()) # String strip() 76 | elif field[0] == 'Country': 77 | country = field[1].strip() # String strip() 78 | return ProxyObject(source=self.id, ip=ip, port=port, anonymity_level=anonymity, country=country) 79 | 80 | def __str__(self): 81 | return "ProxyForEU Parser of '{0}' with required bandwidth: '{1}' KBs" \ 82 | .format(self.url, self.minimum_bandwidth_in_KBs) 83 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/SslProxyParser.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import requests 4 | from bs4 import BeautifulSoup 5 | 6 | from http_request_randomizer.requests.parsers.UrlParser import UrlParser 7 | from http_request_randomizer.requests.proxy.ProxyObject import ProxyObject, AnonymityLevel, Protocol 8 | 9 | logger = logging.getLogger(__name__) 10 | __author__ = 'pgaref' 11 | 12 | 13 | class SslProxyParser(UrlParser): 14 | def __init__(self, id, web_url, timeout=None): 15 | UrlParser.__init__(self, id=id, web_url=web_url, timeout=timeout) 16 | 17 | def parse_proxyList(self): 18 | curr_proxy_list = [] 19 | try: 20 | response = requests.get(self.get_url(), timeout=self.timeout) 21 | if not response.ok: 22 | logger.warning("Proxy Provider url failed: {}".format(self.get_url())) 23 | return [] 24 | 25 | content = response.content 26 | soup = BeautifulSoup(content, "html.parser") 27 | table = soup.find("table", attrs={"id": "proxylisttable"}) 28 | 29 | # The first tr contains the field names. 30 | headings = [th.get_text() for th in table.find("tr").find_all("th")] 31 | 32 | datasets = [] 33 | for row in table.find_all("tr")[1:-1]: 34 | dataset = zip(headings, (td.get_text() for td in row.find_all("td"))) 35 | if dataset: 36 | datasets.append(dataset) 37 | 38 | for dataset in datasets: 39 | proxy_obj = self.create_proxy_object(dataset) 40 | # Make sure it is a Valid Proxy Address 41 | if proxy_obj is not None and UrlParser.valid_ip_port(proxy_obj.get_address()): 42 | curr_proxy_list.append(proxy_obj) 43 | else: 44 | logger.debug("Proxy Invalid: {}".format(dataset)) 45 | except AttributeError as e: 46 | logger.error("Provider {0} failed with Attribute error: {1}".format(self.id, e)) 47 | except KeyError as e: 48 | logger.error("Provider {0} failed with Key error: {1}".format(self.id, e)) 49 | except Exception as e: 50 | logger.error("Provider {0} failed with Unknown error: {1}".format(self.id, e)) 51 | finally: 52 | return curr_proxy_list 53 | 54 | def create_proxy_object(self, dataset): 55 | # Check Field[0] for tags and field[1] for values! 56 | ip = "" 57 | port = None 58 | anonymity = AnonymityLevel.UNKNOWN 59 | country = None 60 | protocols = [] 61 | for field in dataset: 62 | if field[0] == 'IP Address': 63 | # Make sure it is a Valid IP 64 | ip = field[1].strip() # String strip() 65 | # Make sure it is a Valid IP 66 | if not UrlParser.valid_ip(ip): 67 | logger.debug("IP with Invalid format: {}".format(ip)) 68 | return None 69 | elif field[0] == 'Port': 70 | port = field[1].strip() # String strip() 71 | elif field[0] == 'Anonymity': 72 | anonymity = AnonymityLevel.get(field[1].strip()) # String strip() 73 | elif field[0] == 'Country': 74 | country = field[1].strip() # String strip() 75 | elif field[0] == 'Https': 76 | if field[1].strip().lower() == 'yes': protocols.extend([Protocol.HTTP, Protocol.HTTPS]) 77 | elif field[1].strip().lower() == 'no': protocols.append(Protocol.HTTP) 78 | return ProxyObject(source=self.id, ip=ip, port=port, anonymity_level=anonymity, country=country, protocols=protocols) 79 | 80 | def __str__(self): 81 | return "{0} parser of '{1}' with required bandwidth: '{2}' KBs" \ 82 | .format(self.id, self.url, self.minimum_bandwidth_in_KBs) 83 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/FreeProxyParser.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import requests 4 | from bs4 import BeautifulSoup 5 | 6 | from http_request_randomizer.requests.parsers.UrlParser import UrlParser 7 | from http_request_randomizer.requests.proxy.ProxyObject import ProxyObject, AnonymityLevel, Protocol 8 | 9 | logger = logging.getLogger(__name__) 10 | __author__ = 'pgaref' 11 | 12 | 13 | class FreeProxyParser(UrlParser): 14 | def __init__(self, id, web_url, timeout=None): 15 | UrlParser.__init__(self, id=id, web_url=web_url, timeout=timeout) 16 | 17 | def parse_proxyList(self): 18 | curr_proxy_list = [] 19 | try: 20 | response = requests.get(self.get_url(), timeout=self.timeout) 21 | if not response.ok: 22 | logger.warning("Proxy Provider url failed: {}".format(self.get_url())) 23 | return [] 24 | 25 | content = response.content 26 | soup = BeautifulSoup(content, "html.parser") 27 | table = soup.find("table", attrs={"class": "table table-striped table-bordered"}) 28 | 29 | # The first tr contains the field names. 30 | headings = [th.get_text() for th in table.find("tr").find_all("th")] 31 | 32 | datasets = [] 33 | for row in table.find_all("tr")[1:-1]: 34 | dataset = zip(headings, (td.get_text() for td in row.find_all("td"))) 35 | if dataset: 36 | datasets.append(dataset) 37 | 38 | for dataset in datasets: 39 | proxy_obj = self.create_proxy_object(dataset) 40 | # Make sure it is a Valid Proxy Address 41 | if proxy_obj is not None and UrlParser.valid_ip_port(proxy_obj.get_address()): 42 | curr_proxy_list.append(proxy_obj) 43 | else: 44 | logger.debug("Proxy Invalid: {}".format(dataset)) 45 | except AttributeError as e: 46 | logger.error("Provider {0} failed with Attribute error: {1}".format(self.id, e)) 47 | except KeyError as e: 48 | logger.error("Provider {0} failed with Key error: {1}".format(self.id, e)) 49 | except Exception as e: 50 | logger.error("Provider {0} failed with Unknown error: {1}".format(self.id, e)) 51 | finally: 52 | return curr_proxy_list 53 | 54 | def create_proxy_object(self, dataset): 55 | # Check Field[0] for tags and field[1] for values! 56 | ip = "" 57 | port = None 58 | anonymity = AnonymityLevel.UNKNOWN 59 | country = None 60 | protocols = [] 61 | for field in dataset: 62 | if field[0] == 'IP Address': 63 | # Make sure it is a Valid IP 64 | ip = field[1].strip() # String strip() 65 | # Make sure it is a Valid IP 66 | if not UrlParser.valid_ip(ip): 67 | logger.debug("IP with Invalid format: {}".format(ip)) 68 | return None 69 | elif field[0] == 'Port': 70 | port = field[1].strip() # String strip() 71 | elif field[0] == 'Anonymity': 72 | anonymity = AnonymityLevel.get(field[1].strip()) # String strip() 73 | elif field[0] == 'Country': 74 | country = field[1].strip() # String strip() 75 | elif field[0] == 'Https': 76 | if field[1].strip().lower() == 'yes': protocols.extend([Protocol.HTTP, Protocol.HTTPS]) 77 | elif field[1].strip().lower() == 'no': protocols.append(Protocol.HTTP) 78 | return ProxyObject(source=self.id, ip=ip, port=port, anonymity_level=anonymity, country=country, protocols=protocols) 79 | 80 | def __str__(self): 81 | return "{0} parser of '{1}' with required bandwidth: '{2}' KBs" \ 82 | .format(self.id, self.url, self.minimum_bandwidth_in_KBs) 83 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Directly executable script to run the GUI application.""" 3 | 4 | # for macOS packaging support, must be at top of file 5 | from multiprocessing import freeze_support # noqa 6 | 7 | freeze_support() # noqa 8 | 9 | # # logging 10 | # import sys 11 | # sys.stdout = open("logs.txt", "w") 12 | 13 | # UI 14 | from nicegui import native, ui, run # noqa: E402 15 | from multiprocessing import Manager 16 | from monitor import next_search_backoff 17 | 18 | 19 | @ui.page("/") # normal index page (e.g. the entry point of the app) 20 | @ui.page( 21 | "/{_:path}" 22 | ) # all other pages will be handled by the router but must be registered to also show the SPA index page 23 | def main(): 24 | # progressbar 25 | async def countdown_to_next_search(): 26 | ui.notify("Searching...") 27 | # TODO do the actual search 28 | # await search_function() 29 | await run.cpu_bound(next_search_backoff, queue) 30 | await countdown_to_next_search() 31 | 32 | async def start_new_search(drawer): 33 | drawer.hide() 34 | progressbar.visible = True 35 | await countdown_to_next_search() 36 | 37 | # create a queue to communicate with the heavy computation process 38 | queue = Manager().Queue() 39 | # update the progress bar on the main process 40 | ui.timer( 41 | 0.5, 42 | callback=lambda: progressbar.set_value( 43 | queue.get() if not queue.empty() else progressbar.value 44 | ), 45 | ) 46 | # create the UI 47 | progressbar = ui.linear_progress(value=1, show_value=False).props( 48 | "instant-feedback" 49 | ) 50 | progressbar.visible = False 51 | 52 | # menu and tabs 53 | with ui.header().classes(replace="row items-center") as header: 54 | ui.button(on_click=lambda: left_drawer.toggle(), icon="menu").props( 55 | "flat color=white" 56 | ) 57 | with ui.tabs() as tabs: 58 | ui.tab("Results") 59 | ui.tab("Map") 60 | ui.tab("Remote notifications") 61 | ui.tab("Insights") 62 | 63 | with ui.footer(value=False).classes("bg-red-100") as footer: 64 | ui.link( 65 | "Made in California by Floris-Jan Willemsen. Please buy me a coffee: ❤️", 66 | "https://paypal.com", 67 | new_tab=True, 68 | ) 69 | 70 | with ui.left_drawer(value=True, elevated=True).classes( 71 | "bg-blue-100" 72 | ) as left_drawer: 73 | ui.label("Side menu") 74 | # TODO integrate config and parameters via bindings 75 | ui.button( 76 | "Search", icon="search", on_click=lambda e: start_new_search(left_drawer) 77 | ) 78 | 79 | with ui.page_sticky(position="bottom-right", x_offset=20, y_offset=20): 80 | ui.button(on_click=footer.toggle, icon="volunteer_activism").props("fab") 81 | 82 | with ui.tab_panels(tabs, value="Results").classes("w-full"): 83 | with ui.tab_panel("Results"): 84 | ui.label("↩ Open the search menu on the left to start searching 🔎") 85 | ui.label("Available locations:") 86 | with ui.list(): 87 | ui.item("Location 1") 88 | ui.item("Location 2") 89 | with ui.tab_panel("Map"): 90 | ui.label("🛠️ Map functionality is coming soon! 🚧") 91 | # TODO https://nicegui.io/documentation/leaflet 92 | with ui.tab_panel("Remote notifications"): 93 | ui.label("🛠️ Remote notifications are coming soon! 🚧") 94 | # TODO explain and allow configuration of remote notifications 95 | with ui.tab_panel("Insights"): 96 | ui.label("🛠️ Insights are coming soon! 🚧") 97 | # TODO provide plots and data 98 | 99 | 100 | ui.run( 101 | title="Apple Stock Notifier", 102 | reload=False, 103 | native=True, 104 | port=native.find_open_port(), 105 | dark=None, # auto switch based on OS theme 106 | favicon="assets/icon.jpg", 107 | ) 108 | -------------------------------------------------------------------------------- /confighandler.py: -------------------------------------------------------------------------------- 1 | """Module for handling the configuration file, can auto-update and callback on external changes.""" 2 | 3 | from pathlib import Path 4 | from tomlkit import load, dump 5 | from watchfiles import awatch 6 | 7 | 8 | class ConfigHandler: 9 | """Class for handling configuration file reading and manipulation.""" 10 | 11 | def __init__(self, path_to_config_file="./config.toml", auto_update=True) -> None: 12 | """Initialization function. Note that you must listen for file changes by calling `watch_changes`. 13 | 14 | Args: 15 | path_to_config_file (str, optional): the path to the config file. Defaults to "./config.toml". 16 | auto_update (bool, optional): whether to automatically keep the in-memory doc up to date with the on-disk config. Defaults to True. 17 | """ 18 | self.configfile_path = Path(path_to_config_file) 19 | self.auto_update = auto_update 20 | assert self.configfile_path.exists() 21 | self.read() 22 | 23 | def __get_contents_on_disk(self): 24 | with self.configfile_path.open() as fp: 25 | return load(fp) 26 | 27 | def read(self): 28 | """Read the on-disk config to in-memory doc.""" 29 | self.__doc = self.__get_contents_on_disk() 30 | self.searchconfig = Configuration(self) 31 | 32 | def write(self): 33 | """Write the in-memory doc to disk. ATTENTION: this can overwrite changes by others if `auto_update` is not used.""" 34 | with self.configfile_path.open("w+") as fp: 35 | dump(self.__doc, fp) 36 | 37 | def get(self, keys: list[str]): 38 | """Get a value from the config.""" 39 | val = self.__doc.get(keys.pop(0)) if len(keys) > 0 else self.__doc 40 | while len(keys) > 0: 41 | key = keys.pop(0) 42 | val = val[key] 43 | return val 44 | 45 | def set(self, keys: list[str], value: any): 46 | """Set a value in the config. Auto-update config on disk if enabled.""" 47 | dic = self.__doc 48 | for key in keys[:-1]: 49 | dic = dic.setdefault(key, {}) 50 | dic[keys[-1]] = value 51 | if self.auto_update: 52 | self.write() 53 | 54 | def is_outdated(self) -> bool: 55 | """Checks if the in-memory doc is outdated compared to the on-disk file.""" 56 | return self.__get_contents_on_disk() != self.__doc 57 | 58 | async def watch_changes(self, callback_on_external_update=None): 59 | """Watch for changes to the on-disk config file. 60 | 61 | Args: 62 | callback_on_external_update (Callable, optional): callback function that is called after the configuration has been updated by another instance. Defaults to None. 63 | """ 64 | async for _ in awatch(self.configfile_path, poll_delay_ms=1000): 65 | if self.is_outdated(): 66 | if self.auto_update: 67 | self.read() 68 | if callback_on_external_update is not None: 69 | callback_on_external_update() 70 | 71 | 72 | class Configuration: 73 | """Create a configuration of the device and region to search.""" 74 | 75 | def __init__(self, confighandler: ConfigHandler): 76 | searchconfig = confighandler.get(["search"]) 77 | self.country_code = searchconfig.get("country_code", "us") 78 | self.device_family = searchconfig.get("device_family") 79 | self.zip_code = searchconfig.get("zip_code", None) 80 | self.selected_device_models = searchconfig.get("models", []) 81 | self.selected_carriers = searchconfig.get("carriers", []) 82 | self.selected_stores = searchconfig.get("stores", []) 83 | self.appointment_stores = searchconfig.get("appointment_stores", []) 84 | self.regions = self.get_regions() 85 | 86 | def get_regions(self) -> list[str]: 87 | if self.zip_code is not None and len(self.zip_code) > 0: 88 | return [f"location={self.zip_code}"] 89 | elif self.selected_stores is not None: 90 | return [f"store={store}" for store in self.selected_stores] 91 | raise ValueError("Either zip-code region or specific stores must be selected") 92 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/runners/proxyList.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import logging 3 | import sys 4 | 5 | import pkg_resources 6 | 7 | from http_request_randomizer.requests.parsers.FreeProxyParser import FreeProxyParser 8 | from http_request_randomizer.requests.parsers.ProxyForEuParser import ProxyForEuParser 9 | from http_request_randomizer.requests.parsers.RebroWeeblyParser import RebroWeeblyParser 10 | from http_request_randomizer.requests.parsers.PremProxyParser import PremProxyParser 11 | 12 | __author__ = 'pgaref' 13 | 14 | handler = logging.StreamHandler() 15 | formatter = logging.Formatter('%(levelname)-8s %(name)-6s %(message)s') 16 | handler.setFormatter(formatter) 17 | 18 | logging.getLogger().addHandler(handler) 19 | 20 | 21 | class ProxyList(object): 22 | def __init__(self, timeout=1.0, bandwidth=10.0): 23 | # Each of the entries implements a specific URL Parser 24 | self.parsers = dict() 25 | self.parsers['rebro'] = RebroWeeblyParser('ReBro', 'http://rebro.weebly.com', timeout=timeout) 26 | self.parsers['prem'] = PremProxyParser('Prem', 'https://premproxy.com', timeout=timeout) 27 | self.parsers['freeproxy'] = FreeProxyParser('FreeProxy', 'http://free-proxy-list.net', timeout=timeout) 28 | self.parsers['proxyforeu'] = ProxyForEuParser('ProxyForEU', 'http://proxyfor.eu/geo.php', 29 | bandwidth=bandwidth, timeout=timeout) 30 | 31 | def get_source_options(self): 32 | sources = list(map(lambda x: x.id.lower(), self.parsers.values())) 33 | sources.append('all') 34 | return sources 35 | 36 | 37 | def run(args): 38 | # re-initialise with current user settings 39 | proxy_list = ProxyList(bandwidth=args.bandwidth, timeout=args.timeout) 40 | # eliminate duplicates 41 | providers = set(args.source) 42 | # keep proxy list in memory 43 | proxy_out = list() 44 | for source in providers: 45 | if source == 'all': 46 | for p in proxy_list.parsers.values(): 47 | print("* id: {0:<30} url: {1:<50}".format(p.id, p.get_url())) 48 | proxy_out += p.parse_proxyList() 49 | else: 50 | p = proxy_list.parsers[source] 51 | print("* id: {0:<30} url: {1:<50}".format(p.id, p.get_url())) 52 | proxy_out += p.parse_proxyList() 53 | 54 | # dump proxies to output stream 55 | for proxy in proxy_out: 56 | args.outfile.write("{} \n".format(proxy.to_str())) 57 | 58 | 59 | def create_parser(proxyList): 60 | parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, 61 | description='ProxyList tool retrieving proxies from publicly available providers.') 62 | parser.add_argument('-s', '--source', 63 | nargs='+', 64 | choices=proxyList.get_source_options(), 65 | dest='source', 66 | help='Specify proxy provider(s)', 67 | required=True) 68 | 69 | parser.add_argument('-o', '--outfile', 70 | nargs='?', 71 | type=argparse.FileType('w'), 72 | metavar='output-file/sys.stdout', 73 | dest='outfile', 74 | help='Specify output stream', 75 | required=False) 76 | parser.set_defaults(outfile=sys.stdout) 77 | 78 | parser.add_argument('-t', '--timeout', 79 | type=float, 80 | dest='timeout', 81 | help='Specify provider timeout threshold (seconds)', 82 | required=False) 83 | parser.set_defaults(timeout=1.0) 84 | 85 | parser.add_argument('-bw', '--bandwidth', 86 | type=float, 87 | dest='bandwidth', 88 | help='Specify proxy bandwidth threshold (KBs)', 89 | required=False) 90 | parser.set_defaults(bandwidth=10.0) 91 | 92 | version = pkg_resources.require("http_request_randomizer")[0].version 93 | parser.add_argument('-v', '--version', 94 | action='version', 95 | version='%(prog)s {}'.format(version)) 96 | return parser 97 | 98 | 99 | # Wrapper method to satisfy setup.py entry_point 100 | def main(): 101 | parser = create_parser(ProxyList()) 102 | args = parser.parse_args(sys.argv[1:]) 103 | run(args) 104 | print("\n All Done \n") 105 | 106 | 107 | if __name__ == '__main__': 108 | main() 109 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/RebroWeeblyParser.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import requests 4 | from bs4 import BeautifulSoup 5 | 6 | from http_request_randomizer.requests.parsers.UrlParser import UrlParser 7 | from http_request_randomizer.requests.proxy.ProxyObject import ProxyObject, AnonymityLevel 8 | 9 | logger = logging.getLogger(__name__) 10 | __author__ = 'pgaref' 11 | 12 | 13 | class RebroWeeblyParser(UrlParser): 14 | def __init__(self, id, web_url, timeout=None): 15 | self.top_proxy_path = "proxy-list.html" 16 | self.txt_proxy_path = "txt-lists.html" 17 | UrlParser.__init__(self, id=id, web_url=web_url, timeout=timeout) 18 | 19 | def parse_proxyList(self, use_top15k=False): 20 | curr_proxy_list = [] 21 | try: 22 | response = requests.get(self.get_url() + "/" + self.top_proxy_path, timeout=self.timeout) 23 | 24 | if not response.ok: 25 | logger.warning("Proxy Provider url failed: {}".format(self.get_url())) 26 | return [] 27 | 28 | content = response.content 29 | soup = BeautifulSoup(content, "html.parser") 30 | all_divs = soup.findAll("div", attrs={"class": "paragraph", 'style': "text-align:left;"}) 31 | # address_table = soup.find("div", attrs={"class": "paragraph", 'style': "text-align:left;"}) 32 | # .find('font', attrs={'color': '#33a27f'}) 33 | # Parse Top Proxy List page 34 | address_list = [] 35 | country_list = [] 36 | anonymity_list = [] 37 | for div in all_divs: 38 | address_div = div.find('font', attrs={'color': '#33a27f'}) 39 | if address_div is not None: 40 | for row in [x for x in address_div.contents if getattr(x, 'name', None) != 'br']: 41 | address_list.append(str(row)) 42 | curr_div = div.findAll('font', attrs={'size': '2'}) 43 | if curr_div[0] is not None: 44 | row_data = [] 45 | # font -> strong -> font 46 | title = curr_div[0].contents[0].contents[0].contents[0] 47 | for row in [x for x in curr_div[-1].contents if getattr(x, 'name', None) != 'br']: 48 | row_data.append(str(row)) 49 | if 'Country' in str(title): 50 | country_list.extend(row_data) 51 | if 'Status' in str(title): 52 | anonymity_list.extend(row_data) 53 | for address, country, anonymity in zip(address_list, country_list, anonymity_list): 54 | # Make sure it is a Valid Proxy Address 55 | proxy_obj = self.create_proxy_object(address, country, anonymity) 56 | if proxy_obj is not None and UrlParser.valid_ip_port(proxy_obj.get_address()): 57 | curr_proxy_list.append(proxy_obj) 58 | else: 59 | logger.debug("Proxy Invalid: {}".format(row)) 60 | # Usually these proxies are stale 61 | if use_top15k: 62 | # Parse 15k Nodes Text file (named *-all-*.txt) 63 | content = requests.get(self.get_url() + "/" + self.txt_proxy_path).content 64 | soup = BeautifulSoup(content, "html.parser") 65 | table = soup.find("div", attrs={"class": "wsite-multicol-table-wrap"}) 66 | for link in table.findAll('a'): 67 | current_link = link.get('href') 68 | if current_link is not None and "all" in current_link: 69 | self.txt_proxy_path = current_link 70 | more_content = requests.get(self.get_url() + self.txt_proxy_path).text 71 | for proxy_address in more_content.split(): 72 | if UrlParser.valid_ip_port(proxy_address): 73 | proxy_obj = self.create_proxy_object(row) 74 | curr_proxy_list.append(proxy_obj) 75 | except AttributeError as e: 76 | logger.error("Provider {0} failed with Attribute error: {1}".format(self.id, e)) 77 | except KeyError as e: 78 | logger.error("Provider {0} failed with Key error: {1}".format(self.id, e)) 79 | except Exception as e: 80 | logger.error("Provider {0} failed with Unknown error: {1}".format(self.id, e)) 81 | finally: 82 | return curr_proxy_list 83 | 84 | def create_proxy_object(self, address, country, anonymity): 85 | # Make sure it is a Valid IP 86 | ip = address.strip().split(":")[0] 87 | if not UrlParser.valid_ip(ip): 88 | logger.debug("IP with Invalid format: {}".format(ip)) 89 | return None 90 | port = address.strip().split(":")[1] 91 | country = country.strip() 92 | anonymity = AnonymityLevel.get(anonymity.strip()) 93 | 94 | return ProxyObject(source=self.id, ip=ip, port=port, anonymity_level=anonymity, country=country) 95 | 96 | def __str__(self): 97 | return "RebroWeebly Parser of '{0}' with required bandwidth: '{1}' KBs" \ 98 | .format(self.url, self.minimum_bandwidth_in_KBs) 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apple Store Stock Notifier 2 | 3 | 4 | 5 | **This software will immediately send you a notification via Telegram when one of your coveted Apple Devices is available in the selected Apple Stores!** 6 | In addition, it offers various tools (such as graphs) to analyze the availability of the selected devices from the comfort of your smartphone / tablet / teapot / desktop etc. (whatever Telegram runs on). 7 | It is intended to run on an always-on device (such as a Raspberry Pi), and requires an internet connection and a Telegram account. 8 | 9 | This software is built on a modified version of [Apple-Store-Reserve-Monitor](https://github.com/insanoid/Apple-Store-Reserve-Monitor) by [insanoid](https://github.com/insanoid). 10 | 11 | ## Installation (App) 12 | The app can be downloaded from the [releases page](). This is the recommended way for most users. 13 | 14 | ## Installation (CLI) 15 | The pre-built app is recommended for most users, but a CLI is available. 16 | It can be installed as follows: 17 | 1. Clone this repository and `cd` to it. 18 | 2. Execute `pip install -r requirements.txt`. 19 | 3. Adapt the `config.toml` file to your needs (see under "use"). 20 | 4. Create a Telegram bot at @botfather in telegram app to inform you and enter the required details in `config.toml`. 21 | 5. [Create a Telegram API](https://my.telegram.org/apps) to send a message to the bot and enter the required details (api_id, api_hash) in `config.toml`. 22 | 6. Run the monitor with `python remote.py`, or run the app with `python app.py`. 23 | 7. (optional) Send `/setcommands` to the Telegram Botfather chat, select the bot and send the output under "Commands available:" to make the commands easily accessible from the chat. 24 | 8. (optional) to build the GUI app, run `nicegui-pack --windowed --name "Apple Stock Notifier" app.py`. 25 | 26 | Running the pip numpy on the Raspberry Pi can be cumbersome. 27 | If you get errors pertaining to "Importing the numpy C-extensions failed", try running `sudo apt-get install python-dev libatlas-base-dev`. 28 | 29 | ## Use 30 | It's as simple as entering the device and Apple Store you want in `config.json` and running `python module.py`. 31 | The model in `config.json` is the model part number, that can be looked up [here](https://www.techwalls.com/iphone-13-pro-model-number-a2483-a2636-a2638-a2639-a2640-differences/). 32 | The store in `config.json` is the store ID, a list of which can be looked up [here](https://gist.github.com/iF2007/ff127f7722af91c47c0cb44d6c1e961d), defaults to all stores in the zip-code region. To only use specific stores, leave the zip-code empty. If selecting multiple stores without a zip-code region, a separate request will be made for each store. 33 | `config.json` is part of the interface of Apple Store Reserve Monitor, more information on how to use this [here](https://github.com/insanoid/Apple-Store-Reserve-Monitor). 34 | 35 | You can change the parameters regarding intervals, paths, use of proxies etc. from the defaults in `parameters.py`. 36 | 37 | It is recommended to run this on a computer that is always on and always has an active internet connection (think of the environment when doing this!). 38 | Raspberry Pi and similar computing boards are often good choices. 39 | You may want to set up a job to start this automatically using crontab or bashrc if you are running this on a Raspberry Pi, so it can run autonomously. 40 | 41 | **Please use this software responsibly!** 42 | Do not set a low polling interval, both for your own benefit (you will be blocked) as for the other users of Apple's service. 43 | In general, the defaults set are fine for being notified in time. 44 | The intended use is for people to be able to get an Apple device that is often out of stock for their own use. 45 | Do not use this software for scalping, price gouging or any other use that is unethical. 46 | 47 | ## Proxies 48 | Randomized proxies help you make requests for a prolonged period of time without your IP-address being blocked by Apple's server. 49 | For this [http-request-randomizer](https://github.com/pgaref/HTTP_Request_Randomizer#http-request-randomizer-----) by [pgaref](https://github.com/pgaref/HTTP_Request_Randomizer/commits?author=pgaref) (licensed under MIT license) is used. 50 | If randomized proxies are enabled in `parameters.py`, a list of free proxies will be generated. 51 | When a request is made, a random proxy is selected from this list. 52 | If the proxy does not return a response within the timeout window, the proxy is removed from the list. 53 | Because free proxies are often slow and unreliable, for each request, it will fallback to a non-proxied request after attempting a proxy unsuccesfully. 54 | However, because unresponsive proxies are removed from the list, in most cases this random proxy system becomes reliable after a while. 55 | Keep in mind that free proxies only remain active for a very short time (days or even hours), so if this program is ran for a long time, the list will become empty, at which point it reloads the proxy list. 56 | Using the randomized proxies is significantly slower than direct requests, but prevent your IP address from being blocked. 57 | 58 | ## Licensing 59 | This software builts on other open source software. 60 | As such, it is [MIT licensed](). -------------------------------------------------------------------------------- /http_request_randomizer/requests/parsers/PremProxyParser.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import requests 4 | from bs4 import BeautifulSoup 5 | 6 | from http_request_randomizer.requests.parsers.js.UnPacker import JsUnPacker 7 | from http_request_randomizer.requests.parsers.UrlParser import UrlParser 8 | from http_request_randomizer.requests.proxy.ProxyObject import ProxyObject, AnonymityLevel, Protocol 9 | 10 | logger = logging.getLogger(__name__) 11 | __author__ = 'pgaref' 12 | 13 | 14 | # Samair Proxy now renamed to: premproxy.com 15 | class PremProxyParser(UrlParser): 16 | def __init__(self, id, web_url, timeout=None): 17 | self.base_url = web_url 18 | web_url += "/list/" 19 | # Ports decoded by the JS unpacker 20 | self.js_unpacker = None 21 | UrlParser.__init__(self, id=id, web_url=web_url, timeout=timeout) 22 | 23 | def parse_proxyList(self): 24 | curr_proxy_list = [] 25 | try: 26 | # Parse all proxy pages -> format: /list/{num}.htm 27 | # Get the pageRange from the 'pagination' table 28 | page_set = self.get_pagination_set() 29 | logger.debug("Pages: {}".format(page_set)) 30 | # One JS unpacker per provider (not per page) 31 | self.js_unpacker = self.init_js_unpacker() 32 | 33 | for page in page_set: 34 | response = requests.get("{0}{1}".format(self.get_url(), page), timeout=self.timeout) 35 | if not response.ok: 36 | # Could not parse ANY page - Let user know 37 | if not curr_proxy_list: 38 | logger.warning("Proxy Provider url failed: {}".format(self.get_url())) 39 | # Return proxies parsed so far 40 | return curr_proxy_list 41 | content = response.content 42 | soup = BeautifulSoup(content, "html.parser", from_encoding="iso-8859-1") 43 | 44 | table = soup.find("div", attrs={"id": "proxylist"}) 45 | # The first tr contains the field names. 46 | headings = [th.get_text() for th in table.find("tr").find_all("th")] 47 | # skip last 'Select All' row 48 | for row in table.find_all("tr")[1:-1]: 49 | td_row = row.find("td") 50 | portKey = td_row.find('span', attrs={'class': True}).get('class')[0] 51 | port = self.js_unpacker.get_port(portKey) 52 | proxy_obj = self.create_proxy_object(row, port) 53 | # Make sure it is a Valid Proxy Address 54 | if proxy_obj is not None and UrlParser.valid_ip(proxy_obj.ip) and UrlParser.valid_port(port): 55 | curr_proxy_list.append(proxy_obj) 56 | else: 57 | logger.debug("Proxy Invalid: {}".format(proxy_obj.to_str())) 58 | except AttributeError as e: 59 | logger.error("Provider {0} failed with Attribute error: {1}".format(self.id, e)) 60 | except KeyError as e: 61 | logger.error("Provider {0} failed with Key error: {1}".format(self.id, e)) 62 | except Exception as e: 63 | logger.error("Provider {0} failed with Unknown error: {1}".format(self.id, e)) 64 | finally: 65 | return curr_proxy_list 66 | 67 | def get_pagination_set(self): 68 | response = requests.get(self.get_url(), timeout=self.timeout) 69 | page_set = set() 70 | # Could not parse pagination page - Let user know 71 | if not response.ok: 72 | logger.warning("Proxy Provider url failed: {}".format(self.get_url())) 73 | return page_set 74 | content = response.content 75 | soup = BeautifulSoup(content, "html.parser") 76 | for ultag in soup.find_all('ul', {'class': 'pagination'}): 77 | for litag in ultag.find_all('li'): 78 | page_ref = litag.a.get('href') 79 | # Skip current page '/list' 80 | if page_ref.endswith(('htm', 'html')): 81 | page_set.add(page_ref) 82 | else: 83 | page_set.add("") 84 | return page_set 85 | 86 | def init_js_unpacker(self): 87 | response = requests.get(self.get_url(), timeout=self.timeout) 88 | # Could not parse provider page - Let user know 89 | if not response.ok: 90 | logger.warning("Proxy Provider url failed: {}".format(self.get_url())) 91 | return None 92 | content = response.content 93 | soup = BeautifulSoup(content, "html.parser") 94 | 95 | # js file contains the values for the ports 96 | for script in soup.findAll('script'): 97 | if '/js/' in script.get('src'): 98 | jsUrl = self.base_url + script.get('src') 99 | return JsUnPacker(jsUrl) 100 | return None 101 | 102 | def create_proxy_object(self, row, port): 103 | for td_row in row.findAll("td"): 104 | if td_row.attrs['data-label'] == 'IP:port ': 105 | text = td_row.text.strip() 106 | ip = text.split(":")[0] 107 | # Make sure it is a Valid IP 108 | if not UrlParser.valid_ip(ip): 109 | logger.debug("IP with Invalid format: {}".format(ip)) 110 | return None 111 | elif td_row.attrs['data-label'] == 'Anonymity Type: ': 112 | anonymity = AnonymityLevel.get(td_row.text.strip()) 113 | elif td_row.attrs['data-label'] == 'Country: ': 114 | country = td_row.text.strip() 115 | protocols = [Protocol.HTTP] 116 | return ProxyObject(source=self.id, ip=ip, port=port, anonymity_level=anonymity, country=country, protocols=protocols) 117 | 118 | def __str__(self): 119 | return "{0} parser of '{1}' with required bandwidth: '{2}' KBs" \ 120 | .format(self.id, self.url, self.minimum_bandwidth_in_KBs) 121 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/proxy/requestProxy.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import random 4 | import sys 5 | import time 6 | 7 | import requests 8 | from requests.exceptions import ChunkedEncodingError 9 | from requests.exceptions import TooManyRedirects 10 | from requests.exceptions import ConnectionError 11 | from requests.exceptions import ReadTimeout 12 | 13 | from http_request_randomizer.requests.proxy.ProxyObject import Protocol 14 | from http_request_randomizer.requests.errors.ProxyListException import ProxyListException 15 | from http_request_randomizer.requests.parsers.FreeProxyParser import FreeProxyParser 16 | from http_request_randomizer.requests.parsers.ProxyForEuParser import ProxyForEuParser 17 | from http_request_randomizer.requests.parsers.RebroWeeblyParser import RebroWeeblyParser 18 | from http_request_randomizer.requests.parsers.PremProxyParser import PremProxyParser 19 | from http_request_randomizer.requests.parsers.SslProxyParser import SslProxyParser 20 | from http_request_randomizer.requests.useragent.userAgent import UserAgentManager 21 | 22 | __author__ = 'pgaref' 23 | sys.path.insert(0, os.path.abspath('../../../../')) 24 | 25 | # Push back requests library to at least warnings 26 | logging.getLogger("requests").setLevel(logging.WARNING) 27 | logging.getLogger("urllib3").setLevel(logging.WARNING) 28 | handler = logging.StreamHandler() 29 | formatter = logging.Formatter('%(asctime)s %(name)-6s %(levelname)-8s %(message)s') 30 | handler.setFormatter(formatter) 31 | 32 | 33 | class RequestProxy: 34 | def __init__(self, web_proxy_list=[], sustain=False, timeout=5, protocol=Protocol.HTTP, log_level=0): 35 | self.logger = logging.getLogger() 36 | self.logger.addHandler(handler) 37 | self.logger.setLevel(log_level) 38 | self.userAgent = UserAgentManager(file=os.path.join(os.path.dirname(__file__), '../data/user_agents.txt')) 39 | 40 | ##### 41 | # Each of the classes below implements a specific URL Parser 42 | ##### 43 | parsers = list([]) 44 | parsers.append(FreeProxyParser('FreeProxy', 'http://free-proxy-list.net', timeout=timeout)) 45 | #parsers.append(ProxyForEuParser('ProxyForEU', 'http://proxyfor.eu/geo.php', 1.0, timeout=timeout)) <--doesn't work anymore 46 | #parsers.append(RebroWeeblyParser('ReBro', 'http://rebro.weebly.com', timeout=timeout)) <--doesn't work anymore 47 | parsers.append(PremProxyParser('PremProxy', 'https://premproxy.com', timeout=timeout)) 48 | parsers.append(SslProxyParser('SslProxy', 'https://www.sslproxies.org', timeout=timeout)) 49 | 50 | self.logger.debug("=== Initialized Proxy Parsers ===") 51 | for i in range(len(parsers)): 52 | self.logger.debug("\t {0}".format(parsers[i].__str__())) 53 | self.logger.debug("=================================") 54 | 55 | self.sustain = sustain 56 | self.parsers = parsers 57 | self.proxy_list = web_proxy_list 58 | for parser in parsers: 59 | try: 60 | size = len(self.proxy_list) 61 | self.proxy_list += parser.parse_proxyList() 62 | self.logger.debug('Added {} proxies from {}'.format(len(self.proxy_list)-size, parser.id)) 63 | except ReadTimeout: 64 | self.logger.warning("Proxy Parser: '{}' TimedOut!".format(parser.url)) 65 | self.logger.debug('Total proxies = '+str(len(self.proxy_list))) 66 | # filtering the list of available proxies according to user preferences 67 | self.proxy_list = [p for p in self.proxy_list if protocol in p.protocols] 68 | self.logger.debug('Filtered proxies = '+str(len(self.proxy_list))) 69 | self.current_proxy = self.randomize_proxy() 70 | 71 | def set_logger_level(self, level): 72 | self.logger.setLevel(level) 73 | 74 | def get_proxy_list(self): 75 | return self.proxy_list 76 | 77 | def generate_random_request_headers(self): 78 | headers = { 79 | "Connection": "close", # another way to cover tracks 80 | "User-Agent": self.userAgent.get_random_user_agent() 81 | } # select a random user agent 82 | return headers 83 | 84 | def randomize_proxy(self): 85 | if len(self.proxy_list) == 0: 86 | raise ProxyListException("list is empty") 87 | rand_proxy = random.choice(self.proxy_list) 88 | while not rand_proxy: 89 | rand_proxy = random.choice(self.proxy_list) 90 | self.current_proxy = rand_proxy 91 | return rand_proxy 92 | 93 | ##### 94 | # Proxy format: 95 | # http://:@: 96 | ##### 97 | def generate_proxied_request(self, url, method="GET", params={}, data={}, headers={}, req_timeout=30): 98 | try: 99 | random.shuffle(self.proxy_list) 100 | # req_headers = dict(params.items() + self.generate_random_request_headers().items()) 101 | 102 | req_headers = dict(params.items()) 103 | req_headers_random = dict(self.generate_random_request_headers().items()) 104 | req_headers.update(req_headers_random) 105 | 106 | if not self.sustain: 107 | self.randomize_proxy() 108 | 109 | headers.update(req_headers) 110 | 111 | self.logger.debug("Using headers: {0}".format(str(headers))) 112 | self.logger.debug("Using proxy: {0}".format(str(self.current_proxy))) 113 | request = requests.request(method, url, headers=headers, data=data, params=params, timeout=req_timeout, 114 | proxies={ 115 | "http": "http://{0}".format(self.current_proxy.get_address()), 116 | "https": "https://{0}".format(self.current_proxy.get_address()) 117 | }) 118 | # Avoid HTTP request errors 119 | if request.status_code == 409: 120 | raise ConnectionError("HTTP Response [409] - Possible Cloudflare DNS resolution error") 121 | elif request.status_code == 403: 122 | raise ConnectionError("HTTP Response [403] - Permission denied error") 123 | elif request.status_code == 503: 124 | raise ConnectionError("HTTP Response [503] - Service unavailable error") 125 | self.logger.info('RR Status {}'.format(request.status_code)) 126 | return request 127 | except ConnectionError: 128 | try: 129 | self.proxy_list.remove(self.current_proxy) 130 | except ValueError: 131 | pass 132 | self.logger.debug("Proxy unreachable - Removed Straggling proxy: {0} PL Size = {1}".format( 133 | self.current_proxy, len(self.proxy_list))) 134 | self.randomize_proxy() 135 | except ReadTimeout: 136 | try: 137 | self.proxy_list.remove(self.current_proxy) 138 | except ValueError: 139 | pass 140 | self.logger.debug("Read timed out - Removed Straggling proxy: {0} PL Size = {1}".format( 141 | self.current_proxy, len(self.proxy_list))) 142 | self.randomize_proxy() 143 | except ChunkedEncodingError: 144 | try: 145 | self.proxy_list.remove(self.current_proxy) 146 | except ValueError: 147 | pass 148 | self.logger.debug("Wrong server chunked encoding - Removed Straggling proxy: {0} PL Size = {1}".format( 149 | self.current_proxy, len(self.proxy_list))) 150 | self.randomize_proxy() 151 | except TooManyRedirects: 152 | try: 153 | self.proxy_list.remove(self.current_proxy) 154 | except ValueError: 155 | pass 156 | self.logger.debug("Too many redirects - Removed Straggling proxy: {0} PL Size = {1}".format( 157 | self.current_proxy, len(self.proxy_list))) 158 | self.randomize_proxy() 159 | 160 | 161 | if __name__ == '__main__': 162 | 163 | start = time.time() 164 | req_proxy = RequestProxy() 165 | print("Initialization took: {0} sec".format((time.time() - start))) 166 | print("Size: {0}".format(len(req_proxy.get_proxy_list()))) 167 | print("ALL = {0} ".format(list(map(lambda x: x.get_address(), req_proxy.get_proxy_list())))) 168 | 169 | test_url = 'http://ipv4.icanhazip.com' 170 | 171 | while True: 172 | start = time.time() 173 | request = req_proxy.generate_proxied_request(test_url) 174 | print("Proxied Request Took: {0} sec => Status: {1}".format((time.time() - start), request.__str__())) 175 | if request is not None: 176 | print("\t Response: ip={0}".format(u''.join(request.text).encode('utf-8'))) 177 | print("Proxy List Size: {0}".format(len(req_proxy.get_proxy_list()))) 178 | 179 | print("-> Going to sleep..") 180 | time.sleep(10) 181 | -------------------------------------------------------------------------------- /monitor.py: -------------------------------------------------------------------------------- 1 | """Core class for monitoring stores.""" 2 | 3 | import time 4 | import asyncio 5 | from pathlib import Path 6 | from requests.exceptions import ConnectionError 7 | from copy import deepcopy 8 | from math import ceil 9 | from datetime import datetime 10 | from multiprocessing import Queue 11 | 12 | import pandas as pd 13 | import matplotlib.pyplot as plt 14 | 15 | from utils import past_time_formatter 16 | from interface import CallbacksAbstract 17 | from store_checker import StoreChecker 18 | from confighandler import ConfigHandler 19 | 20 | 21 | def next_search_backoff(q: Queue): 22 | """Update the progress bar via the queue.""" 23 | n = 10 24 | for i in range(n): 25 | # Perform some heavy computation 26 | time.sleep(1) 27 | 28 | # Update the progress bar through the queue 29 | q.put_nowait(1 - (i / (n - 1))) 30 | 31 | 32 | class Monitor: 33 | """A class to constantly monitor stock at periodic intervals and report back via callbacks.""" 34 | 35 | def __init__( 36 | self, callbacks: CallbacksAbstract, path_to_config_file="./config.toml" 37 | ): 38 | """Initialization.""" 39 | self.callbacks = callbacks 40 | self.path_to_config_file = path_to_config_file 41 | 42 | # initialize the ConfigHandler and store checker 43 | loop = asyncio.get_event_loop() 44 | init = loop.create_task(self.restart_handler()) 45 | loop.run_until_complete(init) 46 | 47 | # set up the dataframe to store data and the data buffer 48 | if Path(self.confighandler.get(["general", "data_path"])).exists(): 49 | self.df = pd.read_csv( 50 | self.confighandler.get(["general", "data_path"]), index_col=[0] 51 | ) 52 | else: 53 | self.df = pd.DataFrame( 54 | { 55 | "availability": pd.Series(dtype="bool"), 56 | "datetimestamp": pd.Series(dtype="datetime64[ns]"), 57 | "processing_time": pd.Series(dtype="float64"), 58 | } 59 | ) 60 | self.data = self.df.to_dict("records") 61 | print("Apple Store Monitoring\n") 62 | 63 | async def restart_handler(self): 64 | """Callback function to initialize the ConfigHandler and start watching""" 65 | print("Setting up config handler and store checker for Monitor") 66 | self.confighandler = ConfigHandler(self.path_to_config_file) 67 | asyncio.create_task(self.confighandler.watch_changes(self.restart_handler)) 68 | await asyncio.sleep(0.1) # to let the watcher finish setup 69 | # initialize the store checker 70 | self.store_checker = StoreChecker( 71 | self.callbacks, 72 | self.confighandler.searchconfig, 73 | randomize_proxies=self.confighandler.get(["general", "randomize_proxies"]), 74 | ) 75 | 76 | async def start_monitoring(self): 77 | """Start monitoring store stock.""" 78 | 79 | # setup the report counters 80 | count_connection_errors = 0 81 | count = 0 82 | found_availables = list() 83 | processing_time_list = list([0]) 84 | 85 | await self.callbacks.on_start() 86 | 87 | while True: # TODO find a better way? Check that it isn't hogging resources 88 | polling_interval_seconds = self.confighandler.get( 89 | ["general", "polling_interval_seconds"] 90 | ) 91 | try: 92 | # get the new data and write to the data and report buffers 93 | start_time = time.perf_counter() 94 | availability, datetimestamp, refresh_processing_time = ( 95 | await self.store_checker.refresh(verbose=False) 96 | ) 97 | self.data.append( 98 | { 99 | "availability": availability, 100 | "datetimestamp": datetimestamp, 101 | "processing_time": refresh_processing_time, 102 | } 103 | ) 104 | newly_available = availability is True and ( 105 | not found_availables or found_availables[-1] is False 106 | ) 107 | found_availables.append(availability) 108 | count += 1 109 | count_connection_errors += 1 110 | 111 | # if we just changed status from unavailable to available, spam the user to notify 112 | if newly_available: 113 | await self.callbacks.on_newly_available() 114 | 115 | # generate a report if condition is met 116 | if count >= self.confighandler.get( 117 | ["general", "report_after_n_counts"] 118 | ): 119 | 120 | # collect the report data 121 | count_availables = sum(found_availables) 122 | processing_time_list.append(time.perf_counter() - start_time) 123 | processing_time_average = round( 124 | sum(processing_time_list) / len(processing_time_list), 3 125 | ) 126 | 127 | # print the report 128 | report_message = f"Status Report \nIn the past {past_time_formatter(count, polling_interval_seconds)}, iPhones were available {count_availables} out of {len(found_availables)} times. \nThe average processing time was {processing_time_average} seconds." 129 | if self.confighandler.get(["general", "randomize_proxies"]): 130 | report_message += f"\nProxy status: {self.get_proxystatus()}" 131 | await self.callbacks.on_auto_report(report_message) 132 | print(report_message) 133 | 134 | # write the collected data to dataframe and csv 135 | self.save_df() 136 | 137 | # reset the counters for the next report 138 | found_availables = list() 139 | processing_time_list = list([0]) 140 | self.store_checker.statuslist = list() 141 | count = 0 142 | 143 | # subtract the processing time from the sleep counter for accuracte polling intervals 144 | processing_time = time.perf_counter() - start_time 145 | processing_time_list.append(processing_time) 146 | sleep_time = polling_interval_seconds - processing_time 147 | 148 | # if the processing took much longer than the set interval, crash the process and report 149 | if processing_time > polling_interval_seconds * 20: 150 | raise RuntimeError( 151 | f"Processing took more than 20 times longer ({round(processing_time, 3)} seconds) than the set polling interval ({polling_interval_seconds} seconds). To avoid this, look into the cause of the delay (randomized proxies are slow) or increase the interval and reboot." 152 | ) 153 | 154 | # if the processing took longer than the interval, make up the difference by skipping the next polls 155 | if processing_time >= polling_interval_seconds: 156 | additional_start_time = time.perf_counter() 157 | deficit = processing_time - polling_interval_seconds 158 | skips = ceil(deficit / polling_interval_seconds) 159 | await self.callbacks.on_long_processing_warning( 160 | f"Processing took longer ({round(processing_time, 3)} seconds) than the set polling interval ({polling_interval_seconds} seconds). \nSkipping {skips} polling{'s' if skips != 1 else ''}. \nIf you get this message often, disable randomized proxies or increase the polling interval and reboot.", 161 | ) 162 | count += skips 163 | additional_processing_time = ( 164 | time.perf_counter() - additional_start_time 165 | ) 166 | sleep_time = ( 167 | polling_interval_seconds - (deficit % polling_interval_seconds) 168 | ) - additional_processing_time 169 | 170 | # wait for the next polling 171 | sleep_time = max(0, sleep_time) 172 | await asyncio.sleep(sleep_time) 173 | 174 | except ConnectionError as error: 175 | count_connection_errors += 1 176 | backoff_time = polling_interval_seconds * count_connection_errors 177 | message = f"Connection error, the server has likely refused the request because of too many attempts. \nTaking a break for {backoff_time} seconds before attempting again. Error message: {error}" 178 | print(message) 179 | await self.callbacks.on_connection_error(message) 180 | await asyncio.sleep(backoff_time) 181 | 182 | except BaseException as error: 183 | print("Something went wrong!") 184 | await self.callbacks.on_error(error, self.get_logfile_path()) 185 | self.save_df() 186 | raise error 187 | 188 | def get_logfile_path(self): 189 | """Get the path to the logfile or None if it does not exist.""" 190 | log_file = Path(self.confighandler.get(["general", "log_path"])) 191 | return log_file if log_file.exists() else None 192 | 193 | async def stop_monitoring(self): 194 | """Stop the monitoring process""" 195 | print("\nStopping the monitor") 196 | self.save_df() 197 | await self.callbacks.on_stop() 198 | 199 | def save_df(self): 200 | """Save the data to a dataframe and to csv file""" 201 | self.df = pd.DataFrame(self.data) 202 | return self.df.to_csv(self.confighandler.get(["general", "data_path"])) 203 | 204 | def get_proxystatus(self): 205 | """Generate a proxy status message""" 206 | if self.store_checker.randomize_proxies is True: 207 | left = self.store_checker.get_num_proxies() 208 | initial = self.store_checker.initial_num_proxies 209 | proxy_list_refresh_count = self.store_checker.proxy_list_refresh_count 210 | message = f"Proxies were succesful {self.store_checker.count_randomized_proxy_success} times. \nThere are {left} of the initial {initial} proxies left to use. \n{initial-left} proxies have been removed. \nThe proxy list has been assembled {proxy_list_refresh_count} time{'s' if proxy_list_refresh_count != 1 else ''}." 211 | else: 212 | if self.confighandler.get(["general", "randomize_proxies"]) is True: 213 | message = "Randomized proxies were enabled, but there are no active proxies left. \nNon-proxied requests are used." 214 | else: 215 | message = "Randomized proxies are not enabled." 216 | return message 217 | 218 | def plot_over_time(self, yaxis, ylabel) -> str: 219 | """Plot a DF over time, write the plot to disk, return the filepath""" 220 | self.save_df() 221 | 222 | # create a temporary dataframe 223 | plot_df = deepcopy(self.df) 224 | plot_df["availability"] = plot_df["availability"].astype(int) 225 | plot_df = plot_df.set_index("datetimestamp") 226 | plot_df.plot(y=yaxis) 227 | 228 | # configure the plot 229 | fig, ax = plt.gcf(), plt.gca() 230 | fig.set_figheight(6) 231 | fig.set_figwidth(12) 232 | 233 | # set the labels 234 | ax.set_xlabel("Time") 235 | ax.set_ylabel(ylabel) 236 | if yaxis == "processing_time": 237 | # plot the moving average 238 | ma = ( 239 | plot_df["processing_time"] 240 | .rolling( 241 | ceil(self.confighandler.get(["general", "report_after_n_counts"])) 242 | ) 243 | .mean() 244 | ) 245 | plt.plot(ma) 246 | # limit the y-axis 247 | ylimmax = min( 248 | plot_df[yaxis].max(), 249 | self.confighandler.get(["general", "polling_interval_seconds"]), 250 | ) 251 | ax.set_ylim(0, ylimmax) 252 | # dates = self.df["datetimestamp"].to_list() 253 | # dates = [datetime.strptime(x, '%d-%m-%Y %H:%M:%S') for x in dates] 254 | # ax.set_xticks(dates) 255 | fig.autofmt_xdate() 256 | plt.grid() 257 | plt.tight_layout() 258 | 259 | # return the plot to the user 260 | plt.savefig("plots/plot.png", dpi=200) 261 | return "plots/plot.png" 262 | -------------------------------------------------------------------------------- /remote.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Directly executable script for notifications and remote interaction via a Telegram bot.""" 3 | 4 | import os 5 | import asyncio 6 | from pathlib import Path 7 | from requests.exceptions import ConnectionError as RequestConnectionError 8 | from telethon import TelegramClient, events, types, errors 9 | from monitor import Monitor, CallbacksAbstract 10 | from utils import reboot_pi, get_ip 11 | from confighandler import ConfigHandler 12 | 13 | 14 | async def send(client, username: str, message: str, retry_count=0): 15 | """Send a Telegram message""" 16 | try: 17 | await client.send_message(username, message) 18 | except RequestConnectionError as error: 19 | if retry_count >= 5: 20 | print(f"Retried {retry_count} times, auto-rebooting now...") 21 | reboot_pi() 22 | backoff_time = 10 23 | print( 24 | f"ConnectionError on sending Telegram message, waiting {backoff_time} seconds to try again. Error: {error}" 25 | ) 26 | await asyncio.sleep(backoff_time) 27 | await send(client, message, retry_count + 1) 28 | 29 | 30 | # setup callbacks 31 | class Callbacks(CallbacksAbstract): 32 | def __init__(self, client: TelegramClient, username: str) -> None: 33 | self.client = client 34 | self.username = username 35 | self.meta = (client, username) 36 | super().__init__() 37 | 38 | async def on_start(self): 39 | # inform the user that monitoring has commenced 40 | message = f"New monitoring session!\nIP address: {get_ip()}" 41 | print(message) 42 | await send(*self.meta, message) 43 | 44 | async def on_stop(self): 45 | await send(*self.meta, "This bot is done scouting the shelves, goodbye!") 46 | 47 | async def on_stock_available(self, message): 48 | await send(*self.meta, message) 49 | 50 | async def on_appointment_available(self, message): 51 | await send(*self.meta, message) 52 | 53 | async def on_newly_available(self): 54 | for i in range(3): 55 | await send(*self.meta, f"AVAILABLE! {i}") 56 | await asyncio.sleep(1) 57 | 58 | async def on_auto_report(self, report: str): 59 | await send(*self.meta, report) 60 | 61 | async def on_proxy_depletion(self, message: str): 62 | await send(*self.meta, message) 63 | 64 | async def on_long_processing_warning(self, warning: str): 65 | await send(*self.meta, warning) 66 | 67 | async def on_connection_error(self, error): 68 | await send(*self.meta, error) 69 | 70 | async def on_error(self, error: str, logfile_path: Path): 71 | await send( 72 | *self.meta, 73 | f"Oops! Something went wrong, the monitor crashed.\n Reason: {error}", 74 | ) 75 | await self.send_logfile(logfile_path) 76 | 77 | async def send_logfile(self, logfile_path): 78 | """Helper function to send a logfile.""" 79 | if logfile_path is not None: 80 | async with self.client.action(self.username, "document") as action: 81 | await self.client.send_file( 82 | self.username, 83 | logfile_path, 84 | progress_callback=action.progress, 85 | caption="Here's the log file!", 86 | ) 87 | else: 88 | await send( 89 | *self.meta, 90 | f"Can't send the log file because there isn't one at {logfile_path}!", 91 | ) 92 | 93 | 94 | class TelegramConnection: 95 | """Class for sending notifications and receiving commands via a Telegram bot.""" 96 | 97 | def __init__(self, configurationhandler: ConfigHandler) -> None: 98 | # first initialize the Telegram bot 99 | telegramconfig = configurationhandler.get(["telegram"]) 100 | self.api_id = telegramconfig.get("api_id") 101 | self.api_hash = telegramconfig.get("api_hash") 102 | self.bot_token = telegramconfig.get("bot_token") 103 | self.session_name = telegramconfig.get("session_name") 104 | self.username = telegramconfig.get("username") 105 | 106 | # creating a Telegram session and assigning it to a variable client 107 | client = TelegramClient(self.session_name, self.api_id, self.api_hash) 108 | client.parse_mode = "html" 109 | client.start(bot_token=self.bot_token) 110 | 111 | # registering the possible user commands 112 | commands_available = { 113 | "status": "retrieve the most recent check", 114 | "liststatus": "retrieve the statuses over the past report interval", 115 | "proxystatus": "retrieve the current proxy status", 116 | "plotprocessingtime": "plot the processing time over time", 117 | "plotavailability": "plot the availability over time", 118 | "getdata": "get the collected data as a CSV file", 119 | "getlog": "get the log file as a TXT file", 120 | "getconfig": "get the configuration file as a JSON file", 121 | "setconfig": "set the configuration file to the attachment (requires reboot)", 122 | "setpollinginterval": "set the polling interval in seconds (requires reboot)", 123 | "setreportinterval": "set the report interval (requires reboot)", 124 | "reboot": "reboot the Pi", 125 | "terminate": "terminate the monitor (it can no longer be accessed via Telegram!)", 126 | } 127 | commands_available_txt = "Commands available (use /setcommands in the Botfather chat to set these): \n" 128 | for command, description in commands_available.items(): 129 | commands_available_txt += f"{command} - {description}\n" 130 | print(commands_available_txt) 131 | 132 | # set up the monitor 133 | callbacks = Callbacks(client, self.username) 134 | self.monitor = Monitor(callbacks) 135 | 136 | # registering Telegram responses to the requests ((?i) makes it case insensitive) 137 | # status handler 138 | @client.on(events.NewMessage(pattern="(?i)/status")) 139 | async def handle_get_status(event): 140 | status = self.monitor.store_checker.get_last_status() 141 | await event.respond(status) 142 | 143 | # liststatus handler 144 | @client.on(events.NewMessage(pattern="(?i)/liststatus")) 145 | async def handle_list_status(event): 146 | statuslist = self.monitor.store_checker.get_statuslist() 147 | await event.respond(f"Overview of all recent statuses: \n{statuslist}") 148 | 149 | # proxystatus handler 150 | @client.on(events.NewMessage(pattern="(?i)/proxystatus")) 151 | async def handle_proxy_status(event): 152 | await event.respond(self.monitor.get_proxystatus()) 153 | 154 | # termination handler 155 | @client.on(events.NewMessage(pattern="(?i)/terminate")) 156 | async def handle_terminate(event): 157 | self.monitor.save_df() 158 | await event.respond( 159 | "Terminating the monitor... \nTo start the monitor again, reboot." 160 | ) 161 | exit(0) 162 | 163 | # reboot handler 164 | @client.on(events.NewMessage(pattern="(?i)/reboot")) 165 | async def handle_reboot(event): 166 | self.monitor.save_df() 167 | await event.respond("Rebooting, I'll be back...") 168 | reboot_pi() 169 | 170 | # getdata handler 171 | @client.on(events.NewMessage(pattern="(?i)/getdata")) 172 | async def handle_get_data(event): 173 | self.monitor.save_df() 174 | async with client.action(self.username, "document") as action: 175 | await client.send_file( 176 | self.username, 177 | "data.csv", 178 | progress_callback=action.progress, 179 | caption="Here's the data file!", 180 | ) 181 | 182 | # getlog handler 183 | @client.on(events.NewMessage(pattern="(?i)/getlog")) 184 | async def handle_get_log(event): 185 | self.monitor.save_df() 186 | callbacks.send_logfile(self.monitor.get_logfile_path()) 187 | 188 | # plotprocessingtime handler 189 | @client.on(events.NewMessage(pattern="(?i)/plotprocessingtime")) 190 | async def handle_plot_processing_time(event): 191 | filepath = self.monitor.plot_over_time( 192 | yaxis="processing_time", ylabel="Processing time in seconds" 193 | ) 194 | async with client.action(self.username, "photo") as action: 195 | await client.send_file( 196 | self.username, 197 | filepath, 198 | progress_callback=action.progress, 199 | caption="Here's the plot!", 200 | ) 201 | 202 | # plotavailability handler 203 | @client.on(events.NewMessage(pattern="(?i)/plotavailability")) 204 | async def handle_plot_availability(event): 205 | filepath = self.monitor.plot_over_time( 206 | yaxis="availability", ylabel="Available" 207 | ) 208 | async with client.action(self.username, "photo") as action: 209 | await client.send_file( 210 | self.username, 211 | filepath, 212 | progress_callback=action.progress, 213 | caption="Here's the plot!", 214 | ) 215 | 216 | # getconfig handler 217 | @client.on(events.NewMessage(pattern="(?i)/getconfig")) 218 | async def handle_get_config(event): 219 | async with client.action(self.username, "document") as action: 220 | await client.send_file( 221 | self.username, 222 | configurationhandler.configfile_path, 223 | progress_callback=action.progress, 224 | caption="Here's the configuration file!", 225 | ) 226 | 227 | # setconfig handler 228 | @client.on(events.NewMessage(pattern="(?i)/setconfig")) 229 | async def handle_set_config(event): 230 | await event.respond( 231 | f"Attach a new `{configurationhandler.configfile_path}` in your next message and it will be set! Don't forget to delete data.csv in case something relevant changed." 232 | ) 233 | 234 | # general handler for all uploaded files 235 | @client.on(events.NewMessage()) 236 | async def handle_file_upload(event): 237 | if event.document is not None: 238 | # handle new config.json upload 239 | if ( 240 | event.document.mime_type == "application/json" 241 | and types.DocumentAttributeFilename( 242 | configurationhandler.configfile_path 243 | ) 244 | in event.document.attributes 245 | ): 246 | # check if we are in the correct folder before changing anything 247 | if os.path.exists("monitor.py"): 248 | # first remove the old config.json 249 | os.remove(configurationhandler.configfile_path) 250 | # then download the new one 251 | config = await event.download_media() 252 | await event.respond( 253 | f"Succesfully set the new {configurationhandler.configfile_path} ({str(config)}). Reboot to apply." 254 | ) 255 | else: 256 | await event.respond( 257 | f"The current working directory is not the directory of this application. Aborting {configurationhandler.configfile_path} replacement." 258 | ) 259 | else: 260 | await event.respond( 261 | f"If you were trying to set a new {configurationhandler.configfile_path}, make sure the file is named exactly that." 262 | ) 263 | 264 | # ensure client is in class state 265 | self.client = client 266 | 267 | def start(self): 268 | # start the monitoring 269 | with self.client as client: 270 | try: 271 | client.loop.run_until_complete(self.monitor.start_monitoring()) 272 | except KeyboardInterrupt: 273 | client.loop.run_until_complete(self.monitor.stop_monitoring()) 274 | except errors.rpcerrorlist.AuthKeyDuplicatedError as error: 275 | print("Duplicate keys, removing the session file and rebooting") 276 | print(error) 277 | # await send( 278 | # client, 279 | # f"Duplicate keys detected, removing the session files and rebooting. \n\nFull error: \n{error}", 280 | # ) 281 | os.remove("bot.session") 282 | reboot_pi() 283 | 284 | 285 | if __name__ == "__main__": 286 | remote = TelegramConnection(ConfigHandler()) 287 | remote.start() 288 | -------------------------------------------------------------------------------- /store_checker.py: -------------------------------------------------------------------------------- 1 | """Core class for searching stores.""" 2 | 3 | import time 4 | import logging 5 | from datetime import datetime 6 | from typing import Tuple 7 | 8 | import crayons 9 | import minibar 10 | import requests 11 | 12 | from http_request_randomizer.requests.proxy.requestProxy import RequestProxy 13 | from http_request_randomizer.requests.errors.ProxyListException import ( 14 | ProxyListException, 15 | ) 16 | 17 | from interface import CallbacksAbstract 18 | from confighandler import Configuration 19 | 20 | 21 | class StoreChecker: 22 | """Class to handle store checking and fetching and processing of stock of apple products.""" 23 | 24 | # Base URL is the apple's URL used to make product links and also API 25 | # calls. Country code is needed only for non-US countries. 26 | APPLE_BASE_URL = "https://www.apple.com/{0}/" 27 | # End point for searching for all possible product combinations in the 28 | # given product family. 29 | PRODUCT_LOCATOR_URL = "{0}shop/product-locator-meta?family={1}" 30 | # End point for searching for pickup state of a certain model at a certain 31 | # location. 32 | PRODUCT_AVAILABILITY_URL = "{0}shop/retail/pickup-message?pl=true&parts.0={1}&{2}" 33 | # URL for the store availabile 34 | STORE_APPOINTMENT_AVAILABILITY_URL = "https://retail-pz.cdn-apple.com/product-zone-prod/availability/{0}/{1}/availability.json" 35 | # URL for the product buy 36 | PRODUCT_BUY_URL = "{0}shop/buy-iphone/{1}" 37 | 38 | def __init__( 39 | self, 40 | callbacks: CallbacksAbstract, 41 | configuration: Configuration, 42 | randomize_proxies=False, 43 | ): 44 | """Initialize the configuration for checking store(s) for stock.""" 45 | 46 | self.configuration = configuration 47 | self.stores_list_with_stock = {} 48 | self.base_url = "https://www.apple.com/" 49 | self.last_status = "No status available yet, store checker has not completed" 50 | self.status_list = list() 51 | self.device_list = list() 52 | self.callbacks = callbacks 53 | 54 | # set up randomized proxies if specified 55 | self.randomize_proxies = randomize_proxies 56 | self.count_randomized_proxy_success = 0 57 | self.proxy_list_refresh_count = 0 58 | if self.randomize_proxies: 59 | self.refresh_proxies() 60 | 61 | # Since the URL only needs country code for non-US countries, switch the URL for country == US. 62 | if self.configuration.country_code.upper() != "US": 63 | self.base_url = self.APPLE_BASE_URL.format(self.configuration.country_code) 64 | 65 | def get_last_status(self): 66 | return self.last_status 67 | 68 | def get_statuslist(self): 69 | statuslist = "\n".join(self.status_list) 70 | statuslist = statuslist.replace("✔", "✅") 71 | statuslist = statuslist.replace("✖", "❌") 72 | return statuslist 73 | 74 | def refresh_proxies(self): 75 | """Get a new list of proxies""" 76 | try: 77 | print("Assembling a list of proxies to use...\n") 78 | self.req_proxy = RequestProxy(log_level=logging.CRITICAL) 79 | self.initial_num_proxies = self.get_num_proxies() 80 | self.proxy_list_refresh_count += 1 81 | except ProxyListException as error: 82 | print(f"Couldn't find any proxies, not using a proxy! \nError: {error}\n") 83 | self.randomize_proxies = False 84 | 85 | def get_num_proxies(self) -> int: 86 | """Get the number of proxies in the list""" 87 | if self.randomize_proxies is True: 88 | return len(self.req_proxy.get_proxy_list()) 89 | return 0 90 | 91 | async def refresh(self, verbose=True): 92 | """Refresh information about the stock that is available on the Apple website, returns whether it is available""" 93 | start_time = time.perf_counter() 94 | 95 | # only look up the devices once, assuming this only needs to happen once per session 96 | if len(self.device_list) == 0: 97 | print("Looking up the requested devices...\n") 98 | self.device_list = await self.find_devices(verbose) 99 | # Exit if no device was found. 100 | if not self.device_list: 101 | print( 102 | "{}".format( 103 | crayons.red( 104 | "✖ No device matching your configuration was found!" 105 | ) 106 | ) 107 | ) 108 | exit(1) 109 | else: 110 | if verbose: 111 | print( 112 | "{} {} {}".format( 113 | crayons.green("✔ Found"), 114 | len(self.device_list), 115 | crayons.green("devices matching your config."), 116 | ) 117 | ) 118 | print("Retrieving stock and appointment information...") 119 | 120 | # Downloading the list of products from the server. 121 | if verbose: 122 | print( 123 | "{}".format( 124 | crayons.blue( 125 | "➜ Downloading Stock Information for the devices...\n" 126 | ) 127 | ) 128 | ) 129 | 130 | self.stores_list_with_stock = {} 131 | for device in minibar.bar(self.device_list) if verbose else self.device_list: 132 | await self.check_stores_for_device(device) 133 | 134 | # Get all the stores and sort it by the sequence. 135 | stores = list(self.stores_list_with_stock.values()) 136 | stores.sort(key=lambda k: k["sequence"]) 137 | 138 | # Boolean indicating if the stock is available for any of the items 139 | # requested (used to play the sound) 140 | stock_available = False 141 | 142 | # Go through the stores and fetch the stock for all the devices/parts 143 | # in the store and print their status. 144 | message = "" 145 | 146 | def getlink(storePickupProductTitle): 147 | link = self.PRODUCT_BUY_URL.format(self.base_url, "iphone-14") 148 | if "Pro" in storePickupProductTitle: 149 | link += "-pro" 150 | return link 151 | 152 | for store in stores: 153 | if verbose: 154 | print( 155 | "\n\n{}, {} ({})".format( 156 | crayons.green(store.get("storeName")), 157 | crayons.green(store.get("city")), 158 | crayons.green(store.get("storeId")), 159 | ) 160 | ) 161 | message += "\n\n {}, {} ({})\n".format( 162 | store.get("storeName"), store.get("city"), store.get("storeId") 163 | ) 164 | for part_id, part in store.get("parts").items(): 165 | available = ( 166 | part.get("messageTypes").get("regular").get("storeSelectionEnabled") 167 | ) 168 | if available: 169 | stock_available = True 170 | storePickupProductTitle = ( 171 | part.get("messageTypes") 172 | .get("regular") 173 | .get("storePickupProductTitle") 174 | ) 175 | partNumber = part.get("partNumber") 176 | if verbose: 177 | print( 178 | " - {} {} ({})".format( 179 | crayons.green("✔") if available else crayons.red("✖"), 180 | ( 181 | crayons.green(storePickupProductTitle) 182 | if available 183 | else crayons.red(storePickupProductTitle) 184 | ), 185 | ( 186 | crayons.green(partNumber) 187 | if available 188 | else crayons.red(partNumber) 189 | ), 190 | ) 191 | ) 192 | message += "{} {}{}{} ({})\n".format( 193 | "✅" if available else "❌", 194 | ( 195 | f'' 196 | if available 197 | else "" 198 | ), 199 | storePickupProductTitle, 200 | "" if available else "", 201 | partNumber, 202 | ) 203 | 204 | current_datetime = datetime.now().strftime("%d-%m-%Y %H:%M:%S") 205 | processing_time = round(time.perf_counter() - start_time, 3) 206 | self.last_status = f"Status as of {current_datetime} (took {processing_time} seconds): \n{message}" 207 | 208 | # Play the sound if phone is available. 209 | if stock_available: 210 | # immediately send a message! 211 | await self.callbacks.on_stock_available(message) 212 | if verbose: 213 | print( 214 | "\n{}".format(crayons.green("Current Status - Stock is Available")) 215 | ) 216 | else: 217 | short_status = f"✔ {current_datetime} (in {processing_time} seconds)" 218 | self.status_list.append(short_status) 219 | print(crayons.green(short_status)) 220 | elif verbose: 221 | print("\n{}".format(crayons.red("Current Status - No Stock Available"))) 222 | else: 223 | short_status = f"✖ {current_datetime} (in {processing_time} seconds)" 224 | self.status_list.append(short_status) 225 | print(crayons.red(short_status)) 226 | if verbose: 227 | print("\n") 228 | 229 | # lookup the appointment slots if the user has this configured 230 | if not not self.configuration.appointment_stores: 231 | slots_found, message = await self.get_store_availability() 232 | if slots_found is True: 233 | await self.callbacks.on_appointment_available(message) 234 | 235 | return stock_available, current_datetime, processing_time 236 | 237 | async def find_devices(self, verbose=True): 238 | """Find the required devices based on the configuration.""" 239 | # Store the information about the available devices for the family - 240 | # title, model, carrier. 241 | device_list = [] 242 | # Downloading the list of products from the server for the current 243 | # device family. 244 | if verbose: 245 | print("{}".format(crayons.blue("➜ Downloading Models List..."))) 246 | product_locator_response = await self.get_request( 247 | self.PRODUCT_LOCATOR_URL.format( 248 | self.base_url, self.configuration.device_family 249 | ) 250 | ) 251 | if ( 252 | product_locator_response.status_code != 200 253 | or product_locator_response.json() is None 254 | ): 255 | print("----> HERE" + str(device_list)) 256 | return [] 257 | 258 | try: 259 | product_list = ( 260 | product_locator_response.json() 261 | .get("body") 262 | .get("productLocatorOverlayData") 263 | .get("productLocatorMeta") 264 | .get("products") 265 | ) 266 | # Take out the product list and extract only the useful 267 | # information. 268 | for product in product_list: 269 | model = product.get("partNumber") 270 | carrier = product.get("carrierModel") 271 | # Only add the requested models and requested carriers (device 272 | # models are partially matched) 273 | if ( 274 | any( 275 | item in model 276 | for item in self.configuration.selected_device_models 277 | ) 278 | or len(self.configuration.selected_device_models) == 0 279 | ) and ( 280 | carrier in self.configuration.selected_carriers 281 | or len(self.configuration.selected_carriers) == 0 282 | ): 283 | device_list.append( 284 | { 285 | "title": product.get("productTitle"), 286 | "model": model, 287 | "carrier": carrier, 288 | } 289 | ) 290 | except BaseException: 291 | if verbose: 292 | print("{}".format(crayons.red("✖ Failed to find the device family"))) 293 | if self.configuration.selected_device_models is not None: 294 | if verbose: 295 | print( 296 | "{}".format( 297 | crayons.blue("➜ Looking for device models instead...") 298 | ) 299 | ) 300 | for model in self.configuration.selected_device_models: 301 | device_list.append({"model": model}) 302 | print(device_list) 303 | return device_list 304 | 305 | async def check_stores_for_device(self, device, verbose=True): 306 | """Find all stores that have the device requested available (does not matter if it's in stock or not).""" 307 | 308 | # Make a request per region 309 | store_list: list[str] = list() 310 | for region in self.configuration.regions: 311 | product_availability_response = await self.get_request( 312 | self.PRODUCT_AVAILABILITY_URL.format( 313 | self.base_url, device.get("model"), region 314 | ) 315 | ) 316 | if verbose: 317 | print(product_availability_response) 318 | if ( 319 | product_availability_response.status_code != 200 320 | or product_availability_response.json() is None 321 | ): 322 | print("\n{}".format(crayons.red("Cannot get stores!"))) 323 | return 324 | store_list.extend( 325 | product_availability_response.json().get("body").get("stores") 326 | ) 327 | 328 | # Go through all the stores in the list and extract useful information. 329 | # Group products by store (put the stock for this device in the store's 330 | # parts attribute) 331 | for store in store_list: 332 | current_store = self.stores_list_with_stock.get(store.get("storeNumber")) 333 | if current_store is None: 334 | current_store = { 335 | "storeId": store.get("storeNumber"), 336 | "storeName": store.get("storeName"), 337 | "city": store.get("city"), 338 | "sequence": store.get("storeListNumber"), 339 | "parts": {}, 340 | } 341 | new_parts = store.get("partsAvailability") 342 | old_parts = current_store.get("parts") 343 | old_parts.update(new_parts) 344 | current_store["parts"] = old_parts 345 | 346 | # If the store is in the list of user's preferred stores, add it to the 347 | # list to check for stock. 348 | if ( 349 | store.get("storeNumber") in self.configuration.selected_stores 350 | or len(self.configuration.selected_stores) == 0 351 | ): 352 | self.stores_list_with_stock[store.get("storeNumber")] = current_store 353 | 354 | async def get_store_availability(self) -> Tuple[bool, str]: 355 | """Get a list of all the stores to check appointment availability, returns the message to send""" 356 | print( 357 | "{}".format( 358 | crayons.blue("➜ Downloading store appointment availability...\n") 359 | ) 360 | ) 361 | store_availability_list = await self.get_request( 362 | self.STORE_APPOINTMENT_AVAILABILITY_URL.format( 363 | datetime.now().strftime("%Y-%m-%d"), datetime.utcnow().strftime("%H") 364 | ) 365 | ) 366 | message = "" 367 | slots_found = False 368 | for store in store_availability_list.json(): 369 | if store.get("storeNumber") in self.configuration.appointment_stores: 370 | store_number = store.get("storeNumber") 371 | if store.get("appointmentsAvailable") is True: 372 | appointment_datetime = datetime.utcfromtimestamp( 373 | int(store.get("firstAvailableAppointment")) 374 | ).strftime("%d-%m-%Y %H:%M:%S") 375 | message += f"First appointment slot available at {store_number}: {appointment_datetime}\n" 376 | print( 377 | " - Appointment Slot Available: {} {} ({})".format( 378 | crayons.green("✔"), 379 | store_number, 380 | appointment_datetime, 381 | ) 382 | ) 383 | slots_found = True 384 | else: 385 | print(" - {} {}".format(crayons.red("✖"), store_number)) 386 | print("{}".format(crayons.blue("\n✔ Done\n"))) 387 | return slots_found, message 388 | 389 | async def get_request( 390 | self, url: str, proxy_retry_count=0, verbose=True 391 | ) -> requests.Response: 392 | if verbose: 393 | print(url) 394 | """ Wrapper function to execute a get request, optionally with a randomized proxy """ 395 | max_proxy_attempts = 1 396 | if self.randomize_proxies is False or proxy_retry_count >= max_proxy_attempts: 397 | if self.randomize_proxies is True: 398 | print( 399 | crayons.red( 400 | f" randomized proxies failed {max_proxy_attempts} times, falling back to a non-proxied request. If this happens often, consider disabling randomized proxies." 401 | ) 402 | ) 403 | return requests.get(url) 404 | else: 405 | try: 406 | response = self.req_proxy.generate_proxied_request(url, req_timeout=30) 407 | if response is not None and isinstance(response, requests.Response): 408 | self.count_randomized_proxy_success += 1 409 | return response 410 | else: 411 | time.sleep(3) 412 | return await self.get_request(url, proxy_retry_count + 1, verbose) 413 | except ProxyListException: 414 | message = f"Proxy list has been depleted, refreshing the proxy list..." 415 | print(message) 416 | await self.callbacks.on_proxy_depletion(message) 417 | self.refresh_proxies() 418 | return await self.get_request(url) 419 | -------------------------------------------------------------------------------- /http_request_randomizer/requests/data/user_agents.txt: -------------------------------------------------------------------------------- 1 | "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)" 2 | "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)" 3 | "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)" 4 | "Mozilla/4.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)" 5 | "Mozilla/1.22 (compatible; MSIE 10.0; Windows 3.1)" 6 | "Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))" 7 | "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)" 8 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)" 9 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)" 10 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7" 11 | "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; Media Center PC 6.0; Zune 4.0; InfoPath.3; MS-RTC LM 8; .NET4.0C; .NET4.0E)" 12 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)" 13 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)" 14 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Zune 4.0; Tablet PC 2.0; InfoPath.3; .NET4.0C; .NET4.0E)" 15 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0" 16 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; chromeframe/11.0.696.57)" 17 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) chromeframe/10.0.648.205" 18 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; chromeframe/11.0.696.57)" 19 | "Mozilla/5.0 ( ; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" 20 | "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 5.1; Trident/5.0)" 21 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 7.1; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C)" 22 | "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; AskTB5.5)" 23 | "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; InfoPath.2; .NET4.0C; .NET4.0E)" 24 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C)" 25 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; FDM; .NET CLR 1.1.4322; .NET4.0C; .NET4.0E; Tablet PC 2.0)" 26 | "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)" 27 | "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 1.1.4322)" 28 | "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727)" 29 | "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" 30 | "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.0; Trident/4.0; InfoPath.1; SV1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 3.0.04506.30)" 31 | "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.0; Trident/4.0; FBSMTWB; .NET CLR 2.0.34861; .NET CLR 3.0.3746.3218; .NET CLR 3.5.33652; msn OptimizedIE8;ENUS)" 32 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)" 33 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; Media Center PC 6.0; InfoPath.2; MS-RTC LM 8)" 34 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; Media Center PC 6.0; InfoPath.2; MS-RTC LM 8" 35 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; Media Center PC 6.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C)" 36 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; InfoPath.3; .NET4.0C; .NET4.0E; .NET CLR 3.5.30729; .NET CLR 3.0.30729; MS-RTC LM 8)" 37 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; InfoPath.2)" 38 | "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; Zune 3.0)" 39 | "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; msn OptimizedIE8;ZHCN)" 40 | "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; MS-RTC LM 8; InfoPath.3; .NET4.0C; .NET4.0E) chromeframe/8.0.552.224" 41 | "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; MS-RTC LM 8; .NET4.0C; .NET4.0E; Zune 4.7; InfoPath.3)" 42 | "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; MS-RTC LM 8; .NET4.0C; .NET4.0E; Zune 4.7)" 43 | "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; MS-RTC LM 8)" 44 | "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.3; Zune 4.0)" 45 | "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.3; .NET4.0C; .NET4.0E; MS-RTC LM 8; Zune 4.7)" 46 | "Mozilla/5.0 (X11; Linux x86_64; rv:2.2a1pre) Gecko/20110324 Firefox/4.2a1pre" 47 | "Mozilla/5.0 (X11; Linux x86_64; rv:2.2a1pre) Gecko/20100101 Firefox/4.2a1pre" 48 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.2a1pre) Gecko/20110324 Firefox/4.2a1pre" 49 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.2a1pre) Gecko/20110323 Firefox/4.2a1pre" 50 | "Mozilla/5.0 (X11; Linux x86_64; rv:2.0b9pre) Gecko/20110111 Firefox/4.0b9pre" 51 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b9pre) Gecko/20101228 Firefox/4.0b9pre" 52 | "Mozilla/5.0 (Windows NT 5.1; rv:2.0b9pre) Gecko/20110105 Firefox/4.0b9pre" 53 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b8pre) Gecko/20101114 Firefox/4.0b8pre" 54 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b8pre) Gecko/20101213 Firefox/4.0b8pre" 55 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b8pre) Gecko/20101128 Firefox/4.0b8pre" 56 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b8pre) Gecko/20101114 Firefox/4.0b8pre" 57 | "Mozilla/5.0 (Windows NT 5.1; rv:2.0b8pre) Gecko/20101127 Firefox/4.0b8pre" 58 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b8) Gecko/20100101 Firefox/4.0b8" 59 | "Mozilla/5.0 (Windows NT 6.1; rv:2.0b7pre) Gecko/20100921 Firefox/4.0b7pre" 60 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b7) Gecko/20101111 Firefox/4.0b7" 61 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b7) Gecko/20100101 Firefox/4.0b7" 62 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b6pre) Gecko/20100903 Firefox/4.0b6pre" 63 | "Mozilla/5.0 (Windows NT 6.1; rv:2.0b6pre) Gecko/20100903 Firefox/4.0b6pre Firefox/4.0b6pre" 64 | "Mozilla/5.0 (X11; Linux x86_64; rv:2.0b4) Gecko/20100818 Firefox/4.0b4" 65 | "Mozilla/5.0 (X11; Linux i686; rv:2.0b3pre) Gecko/20100731 Firefox/4.0b3pre" 66 | "Mozilla/5.0 (Windows NT 5.2; rv:2.0b13pre) Gecko/20110304 Firefox/4.0b13pre" 67 | "Mozilla/5.0 (Windows NT 5.1; rv:2.0b13pre) Gecko/20110223 Firefox/4.0b13pre" 68 | "Mozilla/5.0 (X11; Linux i686; rv:2.0b12pre) Gecko/20110204 Firefox/4.0b12pre" 69 | "Mozilla/5.0 (X11; Linux i686; rv:2.0b12pre) Gecko/20100101 Firefox/4.0b12pre" 70 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b11pre) Gecko/20110128 Firefox/4.0b11pre" 71 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b11pre) Gecko/20110131 Firefox/4.0b11pre" 72 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b11pre) Gecko/20110129 Firefox/4.0b11pre" 73 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b11pre) Gecko/20110128 Firefox/4.0b11pre" 74 | "Mozilla/5.0 (Windows NT 6.1; rv:2.0b11pre) Gecko/20110126 Firefox/4.0b11pre" 75 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b11pre) Gecko/20110126 Firefox/4.0b11pre" 76 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b10pre) Gecko/20110118 Firefox/4.0b10pre" 77 | "Mozilla/5.0 (Windows NT 6.1; rv:2.0b10pre) Gecko/20110113 Firefox/4.0b10pre" 78 | "Mozilla/5.0 (X11; Linux i686; rv:2.0b10) Gecko/20100101 Firefox/4.0b10" 79 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:2.0b10) Gecko/20110126 Firefox/4.0b10" 80 | "Mozilla/5.0 (Windows NT 6.1; rv:2.0b10) Gecko/20110126 Firefox/4.0b10" 81 | "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:2.0) Gecko/20110307 Firefox/4.0" 82 | "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:2.0) Gecko/20110404 Fedora/16-dev Firefox/4.0" 83 | "Mozilla/5.0 (X11; Arch Linux i686; rv:2.0) Gecko/20110321 Firefox/4.0" 84 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)" 85 | "Mozilla/5.0 (Windows NT 6.1; rv:2.0) Gecko/20110319 Firefox/4.0" 86 | "Mozilla/5.0 (Windows NT 6.1; rv:1.9) Gecko/20100101 Firefox/4.0" 87 | "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8" 88 | "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/2008092313 Ubuntu/9.25 (jaunty) Firefox/3.8" 89 | "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.9.0.2) Gecko/2008092313 Ubuntu/9.25 (jaunty) Firefox/3.8" 90 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.3) Gecko/20100401 Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.9.0.2) Gecko/2008092313 Ubuntu/9.25 (jaunty) Firefox/3.8" 91 | "Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.3a5pre) Gecko/20100526 Firefox/3.7a5pre" 92 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2b5) Gecko/20091204 Firefox/3.6b5" 93 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2b5) Gecko/20091204 Firefox/3.6b5" 94 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2b5) Gecko/20091204 Firefox/3.6b5" 95 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20091218 Firefox 3.6b5" 96 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2b4) Gecko/20091124 Firefox/3.6b4 (.NET CLR 3.5.30729)" 97 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2b4) Gecko/20091124 Firefox/3.6b4" 98 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2b1) Gecko/20091014 Firefox/3.6b1 GTB5" 99 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2a1pre) Gecko/20090428 Firefox/3.6a1pre" 100 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2a1pre) Gecko/20090405 Firefox/3.6a1pre" 101 | "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.9.2a1pre) Gecko/20090405 Ubuntu/9.04 (jaunty) Firefox/3.6a1pre" 102 | "Mozilla/5.0 (Windows; Windows NT 5.1; es-ES; rv:1.9.2a1pre) Gecko/20090402 Firefox/3.6a1pre" 103 | "Mozilla/5.0 (Windows; Windows NT 5.1; en-US; rv:1.9.2a1pre) Gecko/20090402 Firefox/3.6a1pre" 104 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2a1pre) Gecko/20090402 Firefox/3.6a1pre (.NET CLR 3.5.30729)" 105 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100915 Gentoo Firefox/3.6.9" 106 | "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.9.2.9) Gecko/20100913 Firefox/3.6.9" 107 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2.9) Gecko/20100824 Firefox/3.6.9 ( .NET CLR 3.5.30729; .NET CLR 4.0.20506)" 108 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-GB; rv:1.9.2.9) Gecko/20100824 Firefox/3.6.9" 109 | "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.9.2.8) Gecko/20101230 Firefox/3.6.8" 110 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.8) Gecko/20100804 Gentoo Firefox/3.6.8" 111 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.8) Gecko/20100723 SUSE/3.6.8-0.1.1 Firefox/3.6.8" 112 | "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.2.8) Gecko/20100722 Ubuntu/10.04 (lucid) Firefox/3.6.8" 113 | "Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8" 114 | "Mozilla/5.0 (X11; U; Linux i686; fi-FI; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8" 115 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.8) Gecko/20100727 Firefox/3.6.8" 116 | "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.9.2.8) Gecko/20100725 Gentoo Firefox/3.6.8" 117 | "Mozilla/5.0 (X11; U; FreeBSD i386; de-CH; rv:1.9.2.8) Gecko/20100729 Firefox/3.6.8" 118 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8" 119 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 GTB7.1" 120 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; it; rv:1.9.2.8) Gecko/20100722 AskTbADAP/3.9.1.14019 Firefox/3.6.8" 121 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; he; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8" 122 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2.8) Gecko/20100722 Firefox 3.6.8 GTB7.1" 123 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0C)" 124 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2.8) Gecko/20100722 Firefox 3.6.8" 125 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2.3) Gecko/20121221 Firefox/3.6.8" 126 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-TW; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8" 127 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8" 128 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E" 129 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.7) Gecko/20100809 Fedora/3.6.7-1.fc14 Firefox/3.6.7" 130 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.7) Gecko/20100723 Fedora/3.6.7-1.fc13 Firefox/3.6.7" 131 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.7) Gecko/20100726 CentOS/3.6-3.el5.centos Firefox/3.6.7" 132 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; hu; rv:1.9.2.7) Gecko/20100713 Firefox/3.6.7 GTB7.1" 133 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.7 (.NET CLR 3.5.30729)" 134 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.9.2.7) Gecko/20100713 Firefox/3.6.7 (.NET CLR 3.5.30729)" 135 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6 GTB7.1" 136 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6 GTB7.0" 137 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6 (.NET CLR 3.5.30729)" 138 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6" 139 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-PT; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6" 140 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; it; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 ( .NET CLR 3.5.30729)" 141 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 (.NET CLR 3.5.30729)" 142 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 GTB7.1" 143 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; nl; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6" 144 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 ( .NET CLR 3.5.30729; .NET4.0E)" 145 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.4) Gecko/20100614 Ubuntu/10.04 (lucid) Firefox/3.6.4" 146 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.4) Gecko/20100625 Gentoo Firefox/3.6.4" 147 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-TW; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 ( .NET CLR 3.5.30729)" 148 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4" 149 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ja; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 GTB7.1" 150 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; cs; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 (.NET CLR 3.5.30729)" 151 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4" 152 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 ( .NET CLR 3.5.30729)" 153 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.9.2.4) Gecko/20100523 Firefox/3.6.4 ( .NET CLR 3.5.30729)" 154 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.4) Gecko/20100527 Firefox/3.6.4 (.NET CLR 3.5.30729)" 155 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.4) Gecko/20100527 Firefox/3.6.4" 156 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.4) Gecko/20100523 Firefox/3.6.4 ( .NET CLR 3.5.30729)" 157 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 (.NET CLR 3.5.30729)" 158 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-CA; rv:1.9.2.4) Gecko/20100523 Firefox/3.6.4" 159 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 GTB7.0 ( .NET CLR 3.5.30729)" 160 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 (.NET CLR 3.5.30729)" 161 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.4) Gecko/20100503 Firefox/3.6.4 ( .NET CLR 3.5.30729)" 162 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; nb-NO; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 (.NET CLR 3.5.30729)" 163 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ko; rv:1.9.2.4) Gecko/20100523 Firefox/3.6.4" 164 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4" 165 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3pre) Gecko/20100405 Firefox/3.6.3plugin1 ( .NET CLR 3.5.30729)" 166 | "Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.2.3) Gecko/20100403 Fedora/3.6.3-4.fc13 Firefox/3.6.3" 167 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3) Gecko/20100403 Firefox/3.6.3" 168 | "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.3) Gecko/20100401 SUSE/3.6.3-1.1 Firefox/3.6.3" 169 | "Mozilla/5.0 (X11; U; Linux i686; ko-KR; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3" 170 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100404 Ubuntu/10.04 (lucid) Firefox/3.6.3" 171 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.1" 172 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.3" 173 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3" 174 | "Mozilla/5.0 (X11; U; Linux AMD64; en-US; rv:1.9.2.3) Gecko/20100403 Ubuntu/10.10 (maverick) Firefox/3.6.3" 175 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729)" 176 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3" 177 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3" 178 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; it; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3" 179 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; hu; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.1" 180 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.1" 181 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.0 ( .NET CLR 3.5.30729)" 182 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3" 183 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729)" 184 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; cs; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 ( .NET CLR 3.5.30729)" 185 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ca; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729)" 186 | "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2" 187 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 GTB7.0" 188 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.2) Gecko/20100316 AskTbSPC2/3.9.1.14019 Firefox/3.6.2" 189 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 (.NET CLR 3.5.30729)" 190 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 ( .NET CLR 3.5.30729)" 191 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 GTB6 (.NET CLR 3.5.30729)" 192 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 ( .NET CLR 3.0.04506.648)" 193 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 ( .NET CLR 3.0.04506.30)" 194 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.7; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2" 195 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.10pre) Gecko/20100902 Ubuntu/9.10 (karmic) Firefox/3.6.1pre" 196 | "Mozilla/5.0 (X11; U; Linux x86_64; ja-JP; rv:1.9.2.16) Gecko/20110323 Ubuntu/10.10 (maverick) Firefox/3.6.16" 197 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.16) Gecko/20110323 Ubuntu/9.10 (karmic) Firefox/3.6.16 FirePHP/0.5" 198 | "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16" 199 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16" 200 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; pl; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16" 201 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ko; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16 ( .NET CLR 3.5.30729; .NET4.0E)" 202 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16 ( .NET CLR 3.5.30729)" 203 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en; rv:1.9.1.13) Gecko/20100914 Firefox/3.6.16" 204 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.16) Gecko/20110319 AskTbUTR/3.11.3.15590 Firefox/3.6.16" 205 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.16pre) Gecko/20110304 Ubuntu/10.10 (maverick) Firefox/3.6.15pre" 206 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 FirePHP/0.5" 207 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.15) Gecko/20110330 CentOS/3.6-1.el5.centos Firefox/3.6.15" 208 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15" 209 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15 ( .NET CLR 3.5.30729; .NET4.0C) FirePHP/0.5" 210 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2.15) Gecko/20110303 AskTbBT4/3.11.3.15590 Firefox/3.6.15 ( .NET CLR 3.5.30729; .NET4.0C)" 211 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15 (.NET CLR 3.5.30729)" 212 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14pre) Gecko/20110105 Firefox/3.6.14pre" 213 | "Mozilla/5.0 (X11; U; Linux armv7l; en-US; rv:1.9.2.14) Gecko/20110224 Firefox/3.6.14 MB860/Version.0.43.3.MB860.AmericaMovil.en.MX" 214 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.14) Gecko/20110218 Firefox/3.6.14" 215 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-AU; rv:1.9.2.14) Gecko/20110218 Firefox/3.6.14" 216 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.14) Gecko/20110218 Firefox/3.6.14 GTB7.1 ( .NET CLR 3.5.30729)" 217 | "Mozilla/5.0 Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.13) Firefox/3.6.13" 218 | "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.04 (lucid) Firefox/3.6.13" 219 | "Mozilla/5.0 (X11; U; Linux x86_64; nb-NO; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.04 (lucid) Firefox/3.6.13" 220 | "Mozilla/5.0 (X11; U; Linux x86_64; it; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.04 (lucid) Firefox/3.6.13 (.NET CLR 3.5.30729)" 221 | "Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.2.13) Gecko/20110103 Fedora/3.6.13-1.fc14 Firefox/3.6.13" 222 | "Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 223 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101223 Gentoo Firefox/3.6.13" 224 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101219 Gentoo Firefox/3.6.13" 225 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101206 Red Hat/3.6-3.el4 Firefox/3.6.13" 226 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101206 Firefox/3.6.13" 227 | "Mozilla/5.0 (X11; U; Linux x86_64; en-NZ; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13" 228 | "Mozilla/5.0 (X11; U; Linux x86_64; en-GB; rv:1.9.2.13) Gecko/20101206 Ubuntu/9.10 (karmic) Firefox/3.6.13" 229 | "Mozilla/5.0 (X11; U; Linux x86_64; en-GB; rv:1.9.2.13) Gecko/20101206 Red Hat/3.6-2.el5 Firefox/3.6.13" 230 | "Mozilla/5.0 (X11; U; Linux x86_64; da-DK; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13" 231 | "Mozilla/5.0 (X11; U; Linux MIPS32 1074Kf CPS QuadCore; en-US; rv:1.9.2.13) Gecko/20110103 Fedora/3.6.13-1.fc14 Firefox/3.6.13" 232 | "Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13" 233 | "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.9.2.13) Gecko/20101209 Fedora/3.6.13-1.fc13 Firefox/3.6.13" 234 | "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.2.13) Gecko/20101206 Ubuntu/9.10 (karmic) Firefox/3.6.13" 235 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.13) Gecko/20101209 CentOS/3.6-2.el5.centos Firefox/3.6.13" 236 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13" 237 | "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.9.2.12) Gecko/20101030 Firefox/3.6.12" 238 | "Mozilla/5.0 (X11; U; Linux x86_64; es-MX; rv:1.9.2.12) Gecko/20101027 Ubuntu/10.04 (lucid) Firefox/3.6.12" 239 | "Mozilla/5.0 (X11; U; Linux x86_64; es-ES; rv:1.9.2.12) Gecko/20101027 Fedora/3.6.12-1.fc13 Firefox/3.6.12" 240 | "Mozilla/5.0 (X11; U; Linux x86_64; es-ES; rv:1.9.2.12) Gecko/20101026 SUSE/3.6.12-0.7.1 Firefox/3.6.12" 241 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.12) Gecko/20101102 Gentoo Firefox/3.6.12" 242 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.12) Gecko/20101102 Firefox/3.6.12" 243 | "Mozilla/5.0 (X11; U; Linux ppc; fr; rv:1.9.2.12) Gecko/20101027 Ubuntu/10.10 (maverick) Firefox/3.6.12" 244 | "Mozilla/5.0 (X11; U; Linux i686; ko-KR; rv:1.9.2.12) Gecko/20101027 Ubuntu/10.10 (maverick) Firefox/3.6.12" 245 | "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.2.12) Gecko/20101027 Ubuntu/10.10 (maverick) Firefox/3.6.12 GTB7.1" 246 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.12) Gecko/20101027 Fedora/3.6.12-1.fc13 Firefox/3.6.12" 247 | "Mozilla/5.0 (X11; FreeBSD x86_64; rv:2.0) Gecko/20100101 Firefox/3.6.12" 248 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 ( .NET CLR 3.5.30729; .NET4.0E)" 249 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; sv-SE; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12" 250 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 (.NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; .NET CLR 3.5.21022)" 251 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 GTB5" 252 | "Mozilla/5.0 (X11; U; Linux x86_64; ru; rv:1.9.2.11) Gecko/20101028 CentOS/3.6-2.el5.centos Firefox/3.6.11" 253 | "Mozilla/5.0 (X11; U; Linux armv7l; en-GB; rv:1.9.2.3pre) Gecko/20100723 Firefox/3.6.11" 254 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; ru; rv:1.9.2.11) Gecko/20101012 Firefox/3.6.11" 255 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.2.11) Gecko/20101012 Firefox/3.6.11 ( .NET CLR 3.5.30729)" 256 | "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10" 257 | "Mozilla/5.0 (X11; U; Linux x86_64; pt-BR; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10" 258 | "Mozilla/5.0 (X11; U; Linux x86_64; pl-PL; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10" 259 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10 GTB7.1" 260 | "Mozilla/5.0 (X11; U; Linux x86_64; el-GR; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10" 261 | "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10 GTB7.1" 262 | "Mozilla/5.0 (X11; U; Linux x86_64; cs-CZ; rv:1.9.2.10) Gecko/20100915 Ubuntu/10.04 (lucid) Firefox/3.6.10" 263 | "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.2.10) Gecko/20100915 Ubuntu/10.04 (lucid) Firefox/3.6.10" 264 | "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10" 265 | "Mozilla/5.0 (X11; U; Linux i686; es-AR; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10" 266 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.10) Gecko/20100915 Ubuntu/9.04 (jaunty) Firefox/3.6.10" 267 | "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.2.11) Gecko/20101013 Ubuntu/10.10 (maverick) Firefox/3.6.10" 268 | "Mozilla/5.0 (X11; U; Linux i686; en-CA; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10" 269 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10" 270 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.10) Gecko/20100915 Ubuntu/9.10 (karmic) Firefox/3.6.10" 271 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.10) Gecko/20100915 Ubuntu/10.04 (lucid) Firefox/3.6.10" 272 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.10) Gecko/20100914 SUSE/3.6.10-0.3.1 Firefox/3.6.10" 273 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ro; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10" 274 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; nl; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10 ( .NET CLR 3.5.30729)" 275 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10 (.NET CLR 3.5.30729)" 276 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.1) Gecko/20100122 firefox/3.6.1" 277 | "Mozilla/5.0(Windows; U; Windows NT 7.0; rv:1.9.2) Gecko/20100101 Firefox/3.6" 278 | "Mozilla/5.0(Windows; U; Windows NT 5.2; rv:1.9.2) Gecko/20100101 Firefox/3.6" 279 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2) Gecko/20100222 Ubuntu/10.04 (lucid) Firefox/3.6" 280 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2) Gecko/20100130 Gentoo Firefox/3.6" 281 | "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2) Gecko/20100308 Ubuntu/10.04 (lucid) Firefox/3.6" 282 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.2pre) Gecko/20100312 Ubuntu/9.04 (jaunty) Firefox/3.6" 283 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2) Gecko/20100128 Gentoo Firefox/3.6" 284 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2) Gecko/20100115 Ubuntu/10.04 (lucid) Firefox/3.6" 285 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 FirePHP/0.4" 286 | "Mozilla/5.0 (X11; Linux i686; rv:2.0) Gecko/20100101 Firefox/3.6" 287 | "Mozilla/5.0 (X11; FreeBSD i686) Firefox/3.6" 288 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru-RU; rv:1.9.2) Gecko/20100105 MRA 5.6 (build 03278) Firefox/3.6 (.NET CLR 3.5.30729)" 289 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; lt; rv:1.9.2) Gecko/20100115 Firefox/3.6" 290 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.3a3pre) Gecko/20100306 Firefox3.6 (.NET CLR 3.5.30729)" 291 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.8) Gecko/20100806 Firefox/3.6" 292 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.3) Gecko/20100401 Firefox/3.6;MEGAUPLOAD 1.0" 293 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ar; rv:1.9.2) Gecko/20100115 Firefox/3.6" 294 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.2) Gecko/20100115 Firefox/3.6" 295 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.2) Gecko/20100105 Firefox/3.6 (.NET CLR 3.5.30729)" 296 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; pl; rv:1.9.2) Gecko/20100115 Firefox/3.6 ( .NET CLR 3.5.30729)" 297 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b5pre) Gecko/20090517 Firefox/3.5b4pre (.NET CLR 3.5.30729)" 298 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b4pre) Gecko/20090409 Firefox/3.5b4pre" 299 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b4pre) Gecko/20090401 Firefox/3.5b4pre" 300 | "Mozilla/5.0 (X11; U; Linux i686; nl-NL; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4" 301 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4 GTB5 (.NET CLR 3.5.30729)" 302 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4 (.NET CLR 3.5.30729)" 303 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4 (.NET CLR 3.5.30729)" 304 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4" 305 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4 (.NET CLR 3.5.30729)" 306 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4" 307 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; fr; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4" 308 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b4) Gecko/20090423 Firefox/3.5b4 GTB5" 309 | "Mozilla/5.0 (X11; U; Linux x86_64; it; rv:1.9.1.9) Gecko/20100402 Ubuntu/9.10 (karmic) Firefox/3.5.9 (.NET CLR 3.5.30729)" 310 | "Mozilla/5.0 (X11; U; Linux x86_64; it; rv:1.9.1.9) Gecko/20100330 Fedora/3.5.9-2.fc12 Firefox/3.5.9" 311 | "Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.9) Gecko/20100317 SUSE/3.5.9-0.1.1 Firefox/3.5.9 GTB7.0" 312 | "Mozilla/5.0 (X11; U; Linux x86_64; es-CL; rv:1.9.1.9) Gecko/20100402 Ubuntu/9.10 (karmic) Firefox/3.5.9" 313 | "Mozilla/5.0 (X11; U; Linux x86_64; cs-CZ; rv:1.9.1.9) Gecko/20100317 SUSE/3.5.9-0.1.1 Firefox/3.5.9" 314 | "Mozilla/5.0 (X11; U; Linux i686; nl; rv:1.9.1.9) Gecko/20100401 Ubuntu/9.10 (karmic) Firefox/3.5.9" 315 | "Mozilla/5.0 (X11; U; Linux i686; hu-HU; rv:1.9.1.9) Gecko/20100330 Fedora/3.5.9-1.fc12 Firefox/3.5.9" 316 | "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.1.9) Gecko/20100317 SUSE/3.5.9-0.1 Firefox/3.5.9" 317 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100401 Ubuntu/9.10 (karmic) Firefox/3.5.9 GTB7.1" 318 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100315 Ubuntu/9.10 (karmic) Firefox/3.5.9" 319 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.4) Gecko/20091028 Ubuntu/9.10 (karmic) Firefox/3.5.9" 320 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; tr; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 GTB7.1" 321 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; hu; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 (.NET CLR 3.5.30729)" 322 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9" 323 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; et; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9" 324 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9" 325 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; nl; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 ( .NET CLR 3.5.30729)" 326 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; es-ES; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 GTB5 (.NET CLR 3.5.30729)" 327 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.2.13) Gecko/20101203 Firefox/3.5.9 (de)" 328 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 GTB7.0 (.NET CLR 3.0.30618)" 329 | "Mozilla/5.0 (X11; U; Linux x86_64; ru; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc12 Firefox/3.5.8" 330 | "Mozilla/5.0 (X11; U; Linux x86_64; es-ES; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc11 Firefox/3.5.8" 331 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.8) Gecko/20100318 Gentoo Firefox/3.5.8" 332 | "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc12 Firefox/3.5.8" 333 | "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc12 Firefox/3.5.8" 334 | "Mozilla/5.0 (X11; U; Linux i686; es-AR; rv:1.9.1.8) Gecko/20100214 Ubuntu/9.10 (karmic) Firefox/3.5.8" 335 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.8) Gecko/20100214 Ubuntu/9.10 (karmic) Firefox/3.5.8" 336 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8" 337 | "Mozilla/5.0 (X11; U; FreeBSD i386; ja-JP; rv:1.9.1.8) Gecko/20100305 Firefox/3.5.8" 338 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; sl; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8" 339 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 (.NET CLR 3.5.30729) FirePHP/0.4" 340 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 GTB6" 341 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 GTB7.0 (.NET CLR 3.5.30729)" 342 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2) Gecko/20100305 Gentoo Firefox/3.5.7" 343 | "Mozilla/5.0 (X11; U; Linux x86_64; cs-CZ; rv:1.9.1.7) Gecko/20100106 Ubuntu/9.10 (karmic) Firefox/3.5.7" 344 | "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.1.7) Gecko/20091222 SUSE/3.5.7-1.1.1 Firefox/3.5.7" 345 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6" 346 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" 347 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; fr; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.0.04506.648)" 348 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; fa; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7" 349 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 MRA 5.5 (build 02842) Firefox/3.5.7 (.NET CLR 3.5.30729)" 350 | "Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6" 351 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.6) Gecko/20100117 Gentoo Firefox/3.5.6" 352 | "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.6) Gecko/20091216 Fedora/3.5.6-1.fc11 Firefox/3.5.6 GTB6" 353 | "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.1.6) Gecko/20091201 SUSE/3.5.6-1.1.1 Firefox/3.5.6 GTB6" 354 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.6) Gecko/20100118 Gentoo Firefox/3.5.6" 355 | "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6 GTB6" 356 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6 GTB7.0" 357 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6" 358 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.6) Gecko/20091201 SUSE/3.5.6-1.1.1 Firefox/3.5.6" 359 | "Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.9.1.6) Gecko/20100107 Fedora/3.5.6-1.fc12 Firefox/3.5.6" 360 | "Mozilla/5.0 (X11; U; Linux i686; ca; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6" 361 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; it; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6" 362 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 ( .NET CLR 3.5.30729)" 363 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; id; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)" 364 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 MRA 5.4 (build 02647) Firefox/3.5.6 (.NET CLR 3.5.30729)" 365 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)" 366 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 MRA 5.5 (build 02842) Firefox/3.5.6 (.NET CLR 3.5.30729)" 367 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 MRA 5.5 (build 02842) Firefox/3.5.6" 368 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 GTB6 (.NET CLR 3.5.30729) FBSMTWB" 369 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729) FBSMTWB" 370 | "Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.5) Gecko/20091109 Ubuntu/9.10 (karmic) Firefox/3.5.5" 371 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.8pre) Gecko/20091227 Ubuntu/9.10 (karmic) Firefox/3.5.5" 372 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.5) Gecko/20091114 Gentoo Firefox/3.5.5" 373 | "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5" 374 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; uk; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5" 375 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 MRA 5.5 (build 02842) Firefox/3.5.5" 376 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.1.5) Gecko/20091102 MRA 5.5 (build 02842) Firefox/3.5.5" 377 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 ( .NET CLR 3.5.30729)" 378 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.1.5) Gecko/Firefox/3.5.5" 379 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 MRA 5.5 (build 02842) Firefox/3.5.5 (.NET CLR 3.5.30729)" 380 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 MRA 5.5 (build 02842) Firefox/3.5.5" 381 | "Mozilla/5.0 (Windows NT 5.1; U; zh-cn; rv:1.8.1) Gecko/20091102 Firefox/3.5.5" 382 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; pl; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 FBSMTWB" 383 | "Mozilla/5.0 (X11; U; Linux x86_64; ja; rv:1.9.1.4) Gecko/20091016 SUSE/3.5.4-1.1.2 Firefox/3.5.4" 384 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 (.NET CLR 3.5.30729) FBSMTWB" 385 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.4) Gecko/20091007 Firefox/3.5.4" 386 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 (.NET CLR 3.5.30729)" 387 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 ( .NET CLR 3.5.30729; .NET4.0E)" 388 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.4) Gecko/20091007 Firefox/3.5.4" 389 | "Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.5) Gecko/20091109 Ubuntu/9.10 (karmic) Firefox/3.5.3pre" 390 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090914 Slackware/13.0_stable Firefox/3.5.3" 391 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3" 392 | "Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.1.3) Gecko/20091020 Ubuntu/9.10 (karmic) Firefox/3.5.3" 393 | "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3" 394 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.3) Gecko/20090919 Firefox/3.5.3" 395 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.3) Gecko/20090912 Gentoo Firefox/3.5.3 FirePHP/0.3" 396 | "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 GTB5" 397 | "Mozilla/5.0 (X11; U; FreeBSD i386; ru-RU; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3" 398 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3" 399 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 ( .NET CLR 3.5.30729)" 400 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)" 401 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.5.3;MEGAUPLOAD 1.0 ( .NET CLR 3.5.30729)" 402 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3" 403 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3" 404 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ko; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)" 405 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; fi; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3" 406 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 2.0.50727; .NET CLR 3.0.30618; .NET CLR 3.5.21022; .NET CLR 3.5.30729)" 407 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; bg; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)" 408 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)" 409 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ko; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)" 410 | "Mozilla/5.0 (X11; U; Linux x86_64; pl; rv:1.9.1.2) Gecko/20090911 Slackware Firefox/3.5.2" 411 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.2) Gecko/20090803 Slackware Firefox/3.5.2" 412 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.2) Gecko/20090803 Firefox/3.5.2 Slackware" 413 | "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.9.1.2) Gecko/20090804 Firefox/3.5.2" 414 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.2) Gecko/20090729 Slackware/13.0 Firefox/3.5.2" 415 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" 416 | "Mozilla/5.0 (X11; U; Linux i686 (x86_64); fr; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" 417 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)" 418 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)" 419 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; pl; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 GTB7.1 ( .NET CLR 3.5.30729)" 420 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; es-MX; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)" 421 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" 422 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)" 423 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" 424 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" 425 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; uk; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" 426 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" 427 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)" 428 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" 429 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)" 430 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.16) Gecko/20101130 Firefox/3.5.16 FirePHP/0.4" 431 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.1.16) Gecko/20101130 AskTbMYC/3.9.1.14019 Firefox/3.5.16" 432 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; it; rv:1.9.1.16) Gecko/20101130 Firefox/3.5.16 GTB7.1 (.NET CLR 3.5.30729)" 433 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.16) Gecko/20101130 MRA 5.4 (build 02647) Firefox/3.5.16 ( .NET CLR 3.5.30729; .NET4.0C)" 434 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.16) Gecko/20101130 Firefox/3.5.16 GTB7.1" 435 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.16) Gecko/20101130 AskTbPLTV5/3.8.0.12304 Firefox/3.5.16 (.NET CLR 3.5.30729)" 436 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1.16) Gecko/20101130 Firefox/3.5.16 GTB7.1 (.NET CLR 3.5.30729)" 437 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1.16) Gecko/20101130 Firefox/3.5.16 GTB7.1" 438 | "Mozilla/5.0 (X11; U; Linux x86_64; it; rv:1.9.1.15) Gecko/20101027 Fedora/3.5.15-1.fc12 Firefox/3.5.15" 439 | "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.1.15) Gecko/20101027 Fedora/3.5.15-1.fc12 Firefox/3.5.15" 440 | "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru; rv:1.9.1.13) Gecko/20100914 Firefox/3.5.13" 441 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.12) Gecko/2009070611 Firefox/3.5.12" 442 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.12) Gecko/20100824 MRA 5.7 (build 03755) Firefox/3.5.12" 443 | "Mozilla/5.0 (X11; U; Linux; en-US; rv:1.9.1.11) Gecko/20100720 Firefox/3.5.11" 444 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.1.11) Gecko/20100701 Firefox/3.5.11 ( .NET CLR 3.5.30729; .NET4.0C)" 445 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.9.1.11) Gecko/20100701 Firefox/3.5.11 ( .NET CLR 3.5.30729)" 446 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu; rv:1.9.1.11) Gecko/20100701 Firefox/3.5.11" 447 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.10) Gecko/20100504 Firefox/3.5.11 (.NET CLR 3.5.30729)" 448 | "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.1.10) Gecko/20100506 SUSE/3.5.10-0.1.1 Firefox/3.5.10" 449 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1.10) Gecko/20100504 Firefox/3.5.10 GTB7.0 ( .NET CLR 3.5.30729)" 450 | "Mozilla/5.0 (X11; U; Linux x86_64; rv:1.9.1.1) Gecko/20090716 Linux Firefox/3.5.1" 451 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3) Gecko/20100524 Firefox/3.5.1" 452 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.1) Gecko/20090716 Linux Mint/7 (Gloria) Firefox/3.5.1" 453 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.1) Gecko/20090716 Firefox/3.5.1" 454 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.1) Gecko/20090714 SUSE/3.5.1-1.1 Firefox/3.5.1" 455 | "Mozilla/5.0 (X11; U; Linux x86; rv:1.9.1.1) Gecko/20090716 Linux Firefox/3.5.1" 456 | "Mozilla/5.0 (X11; U; Linux i686; nl; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1" 457 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.2pre) Gecko/20090729 Ubuntu/9.04 (jaunty) Firefox/3.5.1" 458 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1 GTB5" 459 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.1) Gecko/20090722 Gentoo Firefox/3.5.1" 460 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.1) Gecko/20090714 SUSE/3.5.1-1.1 Firefox/3.5.1" 461 | "Mozilla/5.0 (X11; U; DragonFly i386; de; rv:1.9.1) Gecko/20090720 Firefox/3.5.1" 462 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.1) Gecko/20090718 Firefox/3.5.1" 463 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1" 464 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; tr; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1 (.NET CLR 3.5.30729)" 465 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; sv-SE; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1 (.NET CLR 3.5.30729)" 466 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1" 467 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1 GTB5 (.NET CLR 4.0.20506)" 468 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1 GTB5 (.NET CLR 3.5.30729)" 469 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.1) Gecko/20090715 Firefox/3.5.1 GTB5 (.NET CLR 3.5.30729)" 470 | "Mozilla/5.0 (X11;U; Linux i686; en-GB; rv:1.9.1) Gecko/20090624 Ubuntu/9.04 (jaunty) Firefox/3.5" 471 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1) Gecko/20090630 Firefox/3.5 GTB6" 472 | "Mozilla/5.0 (X11; U; Linux i686; ja; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)" 473 | "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.9.0.2) Gecko/2008092313 Ubuntu/9.04 (jaunty) Firefox/3.5" 474 | "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.1) Gecko/20090624 Firefox/3.5" 475 | "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.9.1) Gecko/20090624 Ubuntu/9.04 (jaunty) Firefox/3.5" 476 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1) Gecko/20090701 Ubuntu/9.04 (jaunty) Firefox/3.5" 477 | "Mozilla/5.0 (X11; U; Linux i686; en-us; rv:1.9.0.2) Gecko/2008092313 Ubuntu/9.04 (jaunty) Firefox/3.5" 478 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1) Gecko/20090624 Ubuntu/8.04 (hardy) Firefox/3.5" 479 | "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1) Gecko/20090624 Firefox/3.5" 480 | "Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.9.1) Gecko/20090624 Firefox/3.5" 481 | "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.9.1) Gecko/20090703 Firefox/3.5" 482 | "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.9.0.10) Gecko/20090624 Firefox/3.5" 483 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)" 484 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)" 485 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1) Gecko/20090612 Firefox/3.5 (.NET CLR 4.0.20506)" 486 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1) Gecko/20090612 Firefox/3.5" 487 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 4.0.20506)" 488 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.1) Gecko/20090624 Firefox/3.5" 489 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-TW; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)" 490 | "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.25 (KHTML, like Gecko) Chrome/12.0.706.0 Safari/534.25" 491 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24" 492 | "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.702.0 Chrome/12.0.702.0 Safari/534.24" 493 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/12.0.702.0 Safari/534.24" 494 | "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/12.0.702.0 Safari/534.24" 495 | "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.699.0 Safari/534.24" 496 | "Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.699.0 Safari/534.24" 497 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_6) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.698.0 Safari/534.24" 498 | "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.697.0 Safari/534.24" 499 | "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.43 Safari/534.24" 500 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24" 501 | "Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24" 502 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.3 Safari/534.24" 503 | "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.3 Safari/534.24" 504 | "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.3 Safari/534.24" 505 | "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.14 Safari/534.24" 506 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.12 Safari/534.24" 507 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_6) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.12 Safari/534.24" 508 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.04 Chromium/11.0.696.0 Chrome/11.0.696.0 Safari/534.24" 509 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.0 Safari/534.24" 510 | "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.694.0 Safari/534.24" 511 | "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.23 (KHTML, like Gecko) Chrome/11.0.686.3 Safari/534.23" 512 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.21 (KHTML, like Gecko) Chrome/11.0.682.0 Safari/534.21" 513 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.21 (KHTML, like Gecko) Chrome/11.0.678.0 Safari/534.21" 514 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7_0; en-US) AppleWebKit/534.21 (KHTML, like Gecko) Chrome/11.0.678.0 Safari/534.21" 515 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.20 (KHTML, like Gecko) Chrome/11.0.672.2 Safari/534.20" 516 | "Mozilla/5.0 (Windows NT) AppleWebKit/534.20 (KHTML, like Gecko) Chrome/11.0.672.2 Safari/534.20" 517 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-US) AppleWebKit/534.20 (KHTML, like Gecko) Chrome/11.0.672.2 Safari/534.20" 518 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.20 (KHTML, like Gecko) Chrome/11.0.669.0 Safari/534.20" 519 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.19 (KHTML, like Gecko) Chrome/11.0.661.0 Safari/534.19" 520 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.18 (KHTML, like Gecko) Chrome/11.0.661.0 Safari/534.18" 521 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-US) AppleWebKit/534.18 (KHTML, like Gecko) Chrome/11.0.660.0 Safari/534.18" 522 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/11.0.655.0 Safari/534.17" 523 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/11.0.655.0 Safari/534.17" 524 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/11.0.654.0 Safari/534.17" 525 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/11.0.652.0 Safari/534.17" 526 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/10.0.649.0 Safari/534.17" 527 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/10.0.649.0 Safari/534.17" 528 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.82 Safari/534.16" 529 | "Mozilla/5.0 (X11; U; Linux armv7l; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16" 530 | "Mozilla/5.0 (X11; U; FreeBSD x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16" 531 | "Mozilla/5.0 (X11; U; FreeBSD i386; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16" 532 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204" 533 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.134 Safari/534.16" 534 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.134 Safari/534.16" 535 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.134 Safari/534.16" 536 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.134 Safari/534.16" 537 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.648.133 Chrome/10.0.648.133 Safari/534.16" 538 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16" 539 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.648.133 Chrome/10.0.648.133 Safari/534.16" 540 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16" 541 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16" 542 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16" 543 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16" 544 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.648.127 Chrome/10.0.648.127 Safari/534.16" 545 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.127 Safari/534.16" 546 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.127 Safari/534.16" 547 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.127 Safari/534.16" 548 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.11 Safari/534.16" 549 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru-RU) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.11 Safari/534.16" 550 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.11 Safari/534.16" 551 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.648.0 Chrome/10.0.648.0 Safari/534.16" 552 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.648.0 Chrome/10.0.648.0 Safari/534.16" 553 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.0 Safari/534.16" 554 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.642.0 Chrome/10.0.642.0 Safari/534.16" 555 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.639.0 Safari/534.16" 556 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.638.0 Safari/534.16" 557 | "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.634.0 Safari/534.16" 558 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.634.0 Safari/534.16" 559 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 SUSE/10.0.626.0 (KHTML, like Gecko) Chrome/10.0.626.0 Safari/534.16" 560 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Chrome/10.0.613.0 Safari/534.15" 561 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.613.0 Chrome/10.0.613.0 Safari/534.15" 562 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Ubuntu/10.04 Chromium/10.0.612.3 Chrome/10.0.612.3 Safari/534.15" 563 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Chrome/10.0.612.1 Safari/534.15" 564 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.611.0 Chrome/10.0.611.0 Safari/534.15" 565 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.602.0 Safari/534.14" 566 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14" 567 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14" 568 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML,like Gecko) Chrome/9.1.0.0 Safari/540.0" 569 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML, like Gecko) Ubuntu/10.10 Chrome/9.1.0.0 Safari/540.0" 570 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14" 571 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Ubuntu/10.10 Chromium/9.0.600.0 Chrome/9.0.600.0 Safari/534.14" 572 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.600.0 Safari/534.14" 573 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.599.0 Safari/534.13" 574 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.84 Safari/534.13" 575 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.44 Safari/534.13" 576 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.19 Safari/534.13" 577 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13" 578 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13" 579 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.0 Safari/534.13" 580 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.0 Safari/534.13" 581 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.0 Safari/534.13" 582 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.0 Safari/534.13" 583 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.0 Safari/534.13" 584 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.0 Safari/534.13" 585 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.596.0 Safari/534.13" 586 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Ubuntu/10.04 Chromium/9.0.595.0 Chrome/9.0.595.0 Safari/534.13" 587 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Ubuntu/9.10 Chromium/9.0.592.0 Chrome/9.0.592.0 Safari/534.13" 588 | "Mozilla/5.0 (X11; U; Windows NT 6; en-US) AppleWebKit/534.12 (KHTML, like Gecko) Chrome/9.0.587.0 Safari/534.12" 589 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.12 (KHTML, like Gecko) Chrome/9.0.579.0 Safari/534.12" 590 | "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US) AppleWebKit/534.12 (KHTML, like Gecko) Chrome/9.0.576.0 Safari/534.12" 591 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML, like Gecko) Ubuntu/10.10 Chrome/8.1.0.0 Safari/540.0" 592 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.558.0 Safari/534.10" 593 | "Mozilla/5.0 (X11; U; CrOS i686 0.9.130; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.344 Safari/534.10" 594 | "Mozilla/5.0 (X11; U; CrOS i686 0.9.128; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.343 Safari/534.10" 595 | "Mozilla/5.0 (X11; U; CrOS i686 0.9.128; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.341 Safari/534.10" 596 | "Mozilla/5.0 (X11; U; CrOS i686 0.9.128; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.339 Safari/534.10" 597 | "Mozilla/5.0 (X11; U; CrOS i686 0.9.128; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.339" 598 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Ubuntu/10.10 Chromium/8.0.552.237 Chrome/8.0.552.237 Safari/534.10" 599 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/534.10" 600 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/533.3" 601 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/534.10" 602 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10" 603 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10" 604 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10" 605 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.210 Safari/534.10" 606 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.200 Safari/534.10" 607 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.551.0 Safari/534.10" 608 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.548.0 Safari/534.10" 609 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.544.0 Safari/534.10" 610 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.15) Gecko/20101027 Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.540.0 Safari/534.10" 611 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.540.0 Safari/534.10" 612 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.540.0 Safari/534.10" 613 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.540.0 Safari/534.10" 614 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.9 (KHTML, like Gecko) Chrome/7.0.531.0 Safari/534.9" 615 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.8 (KHTML, like Gecko) Chrome/7.0.521.0 Safari/534.8" 616 | "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.24 Safari/534.7" 617 | "Mozilla/5.0 (X11; U; Linux x86_64; fr-FR) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7" 618 | "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7" 619 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7" 620 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.6 (KHTML, like Gecko) Chrome/7.0.500.0 Safari/534.6" 621 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; tr-TR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 622 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ko-KR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 623 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr-FR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 624 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 625 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; cs-CZ) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 626 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja-JP) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 627 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 628 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; zh-cn) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 629 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 630 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 631 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; zh-cn) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 632 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; sv-se) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 633 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; ko-kr) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 634 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 635 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; it-it) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 636 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; fr-fr) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 637 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; es-es) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 638 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 639 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-gb) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 640 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; de-de) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27" 641 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; sv-SE) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 642 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ja-JP) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 643 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 644 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; hu-HU) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 645 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 646 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; de-DE) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 647 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 648 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 649 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 650 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 651 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us) AppleWebKit/534.16+ (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 652 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; fr-ch) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 653 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; de-de) AppleWebKit/534.15+ (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 654 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; ar) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 655 | "Mozilla/5.0 (Android 2.2; Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 656 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-HK) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5" 657 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5" 658 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; tr-TR) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5" 659 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; nb-NO) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5" 660 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; fr-FR) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5" 661 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5" 662 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5" 663 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; zh-cn) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5" 664 | "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8G4 Safari/6533.18.5" 665 | "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_2_1 like Mac OS X; he-il) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5" 666 | "Mozilla/5.0 (iPhone; U; fr; CPU iPhone OS 4_2_1 like Mac OS X; fr) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148a Safari/6533.18.5" 667 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_1 like Mac OS X; zh-tw) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8G4 Safari/6533.18.5" 668 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; pl-pl) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5" 669 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; fr-fr) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5" 670 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5" 671 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; nb-no) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148a Safari/6533.18.5" 672 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; it-it) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148a Safari/6533.18.5" 673 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; fr) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148a Safari/6533.18.5" 674 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; fi-fi) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148a Safari/6533.18.5" 675 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; fi-fi) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5" 676 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8" 677 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; th-th) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8" 678 | "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/531.2+" 679 | "Mozilla/5.0 (X11; U; Linux x86_64; en-ca) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/531.2+" 680 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ja-JP) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 681 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0 Safari/533.16" 682 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0 Safari/533.16" 683 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja-JP) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 684 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; ja-jp) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 685 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; fr) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 686 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; zh-cn) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 687 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; ru-ru) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 688 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; ko-kr) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 689 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; it-it) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 690 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/534.1+ (KHTML, like Gecko) Version/5.0 Safari/533.16" 691 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-au) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 692 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; el-gr) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 693 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; ca-es) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 694 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; zh-tw) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 695 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; ja-jp) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 696 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; it-it) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 697 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; fr-fr) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" 698 | "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-en) AppleWebKit/533.16 (KHTML, like Gecko) Version/4.1 Safari/533.16" 699 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; nl-nl) AppleWebKit/533.16 (KHTML, like Gecko) Version/4.1 Safari/533.16" 700 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; ja-jp) AppleWebKit/533.16 (KHTML, like Gecko) Version/4.1 Safari/533.16" 701 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; de-de) AppleWebKit/533.16 (KHTML, like Gecko) Version/4.1 Safari/533.16" 702 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7; en-us) AppleWebKit/533.4 (KHTML, like Gecko) Version/4.1 Safari/533.4" 703 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en) AppleWebKit/526.9 (KHTML, like Gecko) Version/4.0dp1 Safari/526.8" 704 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; tr) AppleWebKit/528.4+ (KHTML, like Gecko) Version/4.0dp1 Safari/526.11.2" 705 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; en) AppleWebKit/528.4+ (KHTML, like Gecko) Version/4.0dp1 Safari/526.11.2" 706 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; de) AppleWebKit/528.4+ (KHTML, like Gecko) Version/4.0dp1 Safari/526.11.2" 707 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081212 Mozilla/5.0 (Windows; U; Windows NT 5.1; en) AppleWebKit/526.9 (KHTML, like Gecko) Version/4.0dp1 Safari/526.8" 708 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-gb) AppleWebKit/528.10+ (KHTML, like Gecko) Version/4.0dp1 Safari/526.11.2" 709 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_4; en-us) AppleWebKit/528.4+ (KHTML, like Gecko) Version/4.0dp1 Safari/526.11.2" 710 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_4; en-gb) AppleWebKit/528.4+ (KHTML, like Gecko) Version/4.0dp1 Safari/526.11.2" 711 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 712 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 713 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 714 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-gb) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 715 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 716 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; en-us) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 717 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; da-dk) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 718 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; ja-jp) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 719 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.4+ (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 720 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 721 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; de-de) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 722 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; ja-jp) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 723 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" 724 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B5097d Safari/6531.22.7" 725 | "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7" 726 | "Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10gin_lib.cc" 727 | "Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10" 728 | "Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/123" 729 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-TW) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 730 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; ko-KR) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 731 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 732 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 733 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE) AppleWebKit/532+ (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 734 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_4_11; hu-hu) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 735 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/531.21.11 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 736 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; ru-ru) AppleWebKit/533.2+ (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 737 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; de-at) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10" 738 | "Mozilla/5.0 (iPhone; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10" 739 | "Mozilla/5.0 (iPhone Simulator; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7D11 Safari/531.21.10" 740 | "Mozilla/5.0 (iPad; U; CPU OS 3_2_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B500 Safari/53" 741 | "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; es-es) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10" 742 | "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; es-es) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B360 Safari/531.21.10" 743 | "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/7B334b Safari/531.21.1021.10gin_lib.cc" 744 | "Mozilla/5.0 (iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314" 745 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-us) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9" 746 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; en-us) AppleWebKit/532.0+ (KHTML, like Gecko) Version/4.0.3 Safari/531.9.2009" 747 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; en-us) AppleWebKit/532.0+ (KHTML, like Gecko) Version/4.0.3 Safari/531.9" 748 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_1; nl-nl) AppleWebKit/532.3+ (KHTML, like Gecko) Version/4.0.3 Safari/531.9" 749 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; fi-fi) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9" 750 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.3 Safari/531.21.10" 751 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532+ (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 752 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 753 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-TW) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 754 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; pl-PL) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 755 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja-JP) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 756 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; fr-FR) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 757 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 758 | "Mozilla/5.0 (Windows; U; Windows NT 5.2; de-DE) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 759 | "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" 760 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19.1" 761 | "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_7; en-us) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19" 762 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.2 Safari/530.19" 763 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/4.0.1 Safari/530.18" 764 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.19.2 (KHTML, like Gecko) Version/4.0.1 Safari/530.18" 765 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ru-RU) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 766 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja-JP) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 767 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; hu-HU) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 768 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; he-IL) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 769 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; he-IL) AppleWebKit/528+ (KHTML, like Gecko) Version/4.0 Safari/528.16" 770 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; fr-FR) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 771 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; es-es) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 772 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 773 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 774 | "Mozilla/5.0 (Windows; U; Windows NT 6.0; de-DE) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 775 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 776 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 777 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 778 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 779 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 780 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 781 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; nb-NO) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 782 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu-HU) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 783 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 784 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; fi-FI) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16" 785 | "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10" 786 | "Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10" 787 | "Opera/9.80 (X11; Linux x86_64; U; Ubuntu/10.10 (maverick); pl) Presto/2.7.62 Version/11.01" 788 | "Opera/9.80 (X11; Linux i686; U; ja) Presto/2.7.62 Version/11.01" 789 | "Opera/9.80 (X11; Linux i686; U; fr) Presto/2.7.62 Version/11.01" 790 | "Opera/9.80 (Windows NT 6.1; U; zh-tw) Presto/2.7.62 Version/11.01" 791 | "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.7.62 Version/11.01" 792 | "Opera/9.80 (Windows NT 6.1; U; sv) Presto/2.7.62 Version/11.01" 793 | "Opera/9.80 (Windows NT 6.1; U; en-US) Presto/2.7.62 Version/11.01" 794 | "Opera/9.80 (Windows NT 6.1; U; cs) Presto/2.7.62 Version/11.01" 795 | "Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.7.62 Version/11.01" 796 | "Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.7.62 Version/11.01" 797 | "Opera/9.80 (Windows NT 5.1; U;) Presto/2.7.62 Version/11.01" 798 | "Opera/9.80 (Windows NT 5.1; U; cs) Presto/2.7.62 Version/11.01" 799 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101213 Opera/9.80 (Windows NT 6.1; U; zh-tw) Presto/2.7.62 Version/11.01" 800 | "Mozilla/5.0 (Windows NT 6.1; U; nl; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01" 801 | "Mozilla/5.0 (Windows NT 6.1; U; de; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01" 802 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; de) Opera 11.01" 803 | "Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00" 804 | "Opera/9.80 (X11; Linux i686; U; it) Presto/2.7.62 Version/11.00" 805 | "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.6.37 Version/11.00" 806 | "Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.7.62 Version/11.00" 807 | "Opera/9.80 (Windows NT 6.1; U; ko) Presto/2.7.62 Version/11.00" 808 | "Opera/9.80 (Windows NT 6.1; U; fi) Presto/2.7.62 Version/11.00" 809 | "Opera/9.80 (Windows NT 6.1; U; en-GB) Presto/2.7.62 Version/11.00" 810 | "Opera/9.80 (Windows NT 6.1 x64; U; en) Presto/2.7.62 Version/11.00" 811 | "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.7.39 Version/11.00" 812 | "Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.7.39 Version/11.00" 813 | "Opera/9.80 (Windows NT 5.1; U; MRA 5.5 (build 02842); ru) Presto/2.7.62 Version/11.00" 814 | "Opera/9.80 (Windows NT 5.1; U; it) Presto/2.7.62 Version/11.00" 815 | "Mozilla/5.0 (Windows NT 6.0; U; ja; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.00" 816 | "Mozilla/5.0 (Windows NT 5.1; U; pl; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.00" 817 | "Mozilla/5.0 (Windows NT 5.1; U; de; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.00" 818 | "Mozilla/4.0 (compatible; MSIE 8.0; X11; Linux x86_64; pl) Opera 11.00" 819 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; fr) Opera 11.00" 820 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; ja) Opera 11.00" 821 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; en) Opera 11.00" 822 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; pl) Opera 11.00" 823 | "Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.6.31 Version/10.70" 824 | "Mozilla/5.0 (Windows NT 5.2; U; ru; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.70" 825 | "Mozilla/5.0 (Windows NT 5.1; U; zh-cn; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.70" 826 | "Opera/9.80 (Windows NT 5.2; U; zh-cn) Presto/2.6.30 Version/10.63" 827 | "Opera/9.80 (Windows NT 5.2; U; en) Presto/2.6.30 Version/10.63" 828 | "Opera/9.80 (Windows NT 5.1; U; MRA 5.6 (build 03278); ru) Presto/2.6.30 Version/10.63" 829 | "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.6.30 Version/10.62" 830 | "Mozilla/5.0 (X11; Linux x86_64; U; de; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.62" 831 | "Mozilla/4.0 (compatible; MSIE 8.0; X11; Linux x86_64; de) Opera 10.62" 832 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; en) Opera 10.62" 833 | "Opera/9.80 (X11; Linux i686; U; pl) Presto/2.6.30 Version/10.61" 834 | "Opera/9.80 (X11; Linux i686; U; es-ES) Presto/2.6.30 Version/10.61" 835 | "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.6.30 Version/10.61" 836 | "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.6.30 Version/10.61" 837 | "Opera/9.80 (Windows NT 6.0; U; it) Presto/2.6.30 Version/10.61" 838 | "Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.6.30 Version/10.61" 839 | "Opera/9.80 (Windows 98; U; de) Presto/2.6.30 Version/10.61" 840 | "Opera/9.80 (Macintosh; Intel Mac OS X; U; nl) Presto/2.6.30 Version/10.61" 841 | "Opera/9.80 (X11; Linux i686; U; en) Presto/2.5.27 Version/10.60" 842 | "Opera/9.80 (Windows NT 6.0; U; nl) Presto/2.6.30 Version/10.60" 843 | "Opera/10.60 (Windows NT 5.1; U; zh-cn) Presto/2.6.30 Version/10.60" 844 | "Opera/10.60 (Windows NT 5.1; U; en-US) Presto/2.6.30 Version/10.60" 845 | "Opera/9.80 (X11; Linux i686; U; it) Presto/2.5.24 Version/10.54" 846 | "Opera/9.80 (X11; Linux i686; U; en-GB) Presto/2.5.24 Version/10.53" 847 | "Mozilla/5.0 (Windows NT 5.1; U; zh-cn; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.53" 848 | "Mozilla/5.0 (Windows NT 5.1; U; Firefox/5.0; en; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.53" 849 | "Mozilla/5.0 (Windows NT 5.1; U; Firefox/4.5; en; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.53" 850 | "Mozilla/5.0 (Windows NT 5.1; U; Firefox/3.5; en; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.53" 851 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; ko) Opera 10.53" 852 | "Opera/9.80 (Windows NT 6.1; U; fr) Presto/2.5.24 Version/10.52" 853 | "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.5.22 Version/10.51" 854 | "Opera/9.80 (Windows NT 6.0; U; cs) Presto/2.5.22 Version/10.51" 855 | "Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.5.22 Version/10.51" 856 | "Opera/9.80 (Linux i686; U; en) Presto/2.5.22 Version/10.51" 857 | "Mozilla/5.0 (Windows NT 6.1; U; en-GB; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.51" 858 | "Mozilla/5.0 (Linux i686; U; en; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 10.51" 859 | "Mozilla/4.0 (compatible; MSIE 8.0; Linux i686; en) Opera 10.51" 860 | "Opera/9.80 (Windows NT 6.1; U; zh-tw) Presto/2.5.22 Version/10.50" 861 | "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.5.22 Version/10.50" 862 | "Opera/9.80 (Windows NT 6.1; U; sk) Presto/2.6.22 Version/10.50" 863 | "Opera/9.80 (Windows NT 6.1; U; ja) Presto/2.5.22 Version/10.50" 864 | "Opera/9.80 (Windows NT 6.0; U; zh-cn) Presto/2.5.22 Version/10.50" 865 | "Opera/9.80 (Windows NT 5.1; U; sk) Presto/2.5.22 Version/10.50" 866 | "Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.5.22 Version/10.50" 867 | "Opera/10.50 (Windows NT 6.1; U; en-GB) Presto/2.2.2" 868 | "Opera/9.80 (S60; SymbOS; Opera Tablet/9174; U; en) Presto/2.7.81 Version/10.5" 869 | "Opera/9.80 (X11; U; Linux i686; en-US; rv:1.9.2.3) Presto/2.2.15 Version/10.10" 870 | "Opera/9.80 (X11; Linux x86_64; U; it) Presto/2.2.15 Version/10.10" 871 | "Opera/9.80 (Windows NT 6.1; U; de) Presto/2.2.15 Version/10.10" 872 | "Opera/9.80 (Windows NT 6.0; U; Gecko/20100115; pl) Presto/2.2.15 Version/10.10" 873 | "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.2.15 Version/10.10" 874 | "Opera/9.80 (Windows NT 5.1; U; de) Presto/2.2.15 Version/10.10" 875 | "Opera/9.80 (Windows NT 5.1; U; cs) Presto/2.2.15 Version/10.10" 876 | "Mozilla/5.0 (Windows NT 6.0; U; tr; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 10.10" 877 | "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; de) Opera 10.10" 878 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 6.0; tr) Opera 10.10" 879 | "Opera/9.80 (X11; Linux x86_64; U; en-GB) Presto/2.2.15 Version/10.01" 880 | "Opera/9.80 (X11; Linux x86_64; U; en) Presto/2.2.15 Version/10.00" 881 | "Opera/9.80 (X11; Linux x86_64; U; de) Presto/2.2.15 Version/10.00" 882 | "Opera/9.80 (X11; Linux i686; U; ru) Presto/2.2.15 Version/10.00" 883 | "Opera/9.80 (X11; Linux i686; U; pt-BR) Presto/2.2.15 Version/10.00" 884 | "Opera/9.80 (X11; Linux i686; U; pl) Presto/2.2.15 Version/10.00" 885 | "Opera/9.80 (X11; Linux i686; U; nb) Presto/2.2.15 Version/10.00" 886 | "Opera/9.80 (X11; Linux i686; U; en-GB) Presto/2.2.15 Version/10.00" 887 | "Opera/9.80 (X11; Linux i686; U; en) Presto/2.2.15 Version/10.00" 888 | "Opera/9.80 (X11; Linux i686; U; Debian; pl) Presto/2.2.15 Version/10.00" 889 | "Opera/9.80 (X11; Linux i686; U; de) Presto/2.2.15 Version/10.00" 890 | "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.2.15 Version/10.00" 891 | "Opera/9.80 (Windows NT 6.1; U; fi) Presto/2.2.15 Version/10.00" 892 | "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.2.15 Version/10.00" 893 | "Opera/9.80 (Windows NT 6.1; U; de) Presto/2.2.15 Version/10.00" 894 | "Opera/9.80 (Windows NT 6.1; U; cs) Presto/2.2.15 Version/10.00" 895 | "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.2.15 Version/10.00" 896 | "Opera/9.80 (Windows NT 6.0; U; de) Presto/2.2.15 Version/10.00" 897 | "Opera/9.80 (Windows NT 5.2; U; en) Presto/2.2.15 Version/10.00" 898 | "Opera/9.80 (Windows NT 5.1; U; zh-cn) Presto/2.2.15 Version/10.00" 899 | "Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.2.15 Version/10.00" --------------------------------------------------------------------------------