| 7 | |
| 8 | |
| 9 | class BaseCrawler(object): |
| 10 | urls = [] |
| 11 | |
| 12 | @retry(stop_max_attempt_number=3, retry_on_result=lambda x: x is None, wait_fixed=2000) |
| 13 | def fetch(self, url, **kwargs): |
| 14 | try: |
| 15 | headers = Headers(headers=True).generate() |
| 16 | kwargs.setdefault('timeout', GET_TIMEOUT) |
| 17 | kwargs.setdefault('verify', False) |
| 18 | kwargs.setdefault('headers', headers) |
| 19 | response = requests.get(url, **kwargs) |
| 20 | if response.status_code == 200: |
| 21 | response.encoding = 'utf-8' |
| 22 | return response.text |
| 23 | except (requests.ConnectionError, requests.ReadTimeout): |
| 24 | return |
| 25 | |
| 26 | def process(self, html, url): |
| 27 | """ |
| 28 | used for parse html |
| 29 | """ |
| 30 | for proxy in self.parse(html): |
| 31 | logger.info(f'fetched proxy {proxy.string()} from {url}') |
| 32 | yield proxy |
| 33 | |
| 34 | def crawl(self): |
| 35 | """ |
| 36 | crawl main method |
| 37 | """ |
| 38 | try: |
| 39 | for url in self.urls: |
| 40 | logger.info(f'fetching {url}') |
| 41 | html = self.fetch(url) |
| 42 | if not html: |
| 43 | continue |
| 44 | time.sleep(.5) |
| 45 | yield from self.process(html, url) |
| 46 | except RetryError: |
| 47 | logger.error( |
| 48 | f'crawler {self} crawled proxy unsuccessfully, ' |
| 49 | 'please check if target url is valid or network issue') |
nothing calls this directly
no outgoing calls
no test coverage detected