Metadata-Version: 2.1
Name: easy-spider
Version: 1.0.7
Summary: A asynchronous spider with aiohttp
Home-page: https://lin3x.coding.net/p/easy_spider
Author: lin3x
Author-email: 544670411@qq.com
License: UNKNOWN
Description: # Easy Spider
        ## quick start
        ``` python
        from easy_spider import async_env, AsyncSpider, Request, HTMLResponse
            
        class MySpider(AsyncSpider):
        
            def __init__(self):
                super().__init__()
                self.start_targets = ["https://github.blog/"]
        
            def handle(self, response: HTMLResponse):
                titles = response.bs.select(".post-list__item a")
                print([title.text for title in titles])
        
        async_env.run(MySpider())
        ```
        
        本例子中爬取了[github-blog](https://github.blog/) 。其中 `self.start_targets = ["https://github.blog/"]` 设置了初始需要爬取的目标。`handle(self, response: HTMLResponse)` 方法用于处理服务器返回的 `response`，并产生新的需要爬取得目标，这些目标将被放入爬取队列中随后进行爬取。因此 `handle` 方法返回值的类型必须为 `iterable`，或  `handle` 方法自身为一个生成器，当然也可以返回 `None` 或什么都不返回 。在 `easy spider` 中，`AsyncSpider` 已经实现了一个从网页中抽取潜在爬取目标的 `handle` 方法，因此如果需要对[github-blog](https://github.blog/)上存在的 URL 进行进一步的爬取，可以:
        
        ``` python
        def handle(self, response: HTMLResponse):
            titles = response.bs.select(".post-list__item a")
            print([title.text for title in titles])
            yield from super().handle(response)
        ```
        `super().handle(response)` 实际上做了两件事:
        
        1.  获取所有 `a` 标签的 `href` 属性，即页面中可点击的 URL
        3. 使用默认参数将其组装为 `Request` 对象(关于这两个概念将在后面的章节提到)
        
        *注意 `super().handle(response)`  只是产生了新的请求对象，你仍然需要使用 ` yield from ` 将 `handle` 构造为一个生成器。*
        
        此外，`handler` 返回的所有目标还将使用 `self.filter` 筛选出需要的 URL。 `easy_spider.filters.build_in` 内置了几种 `filter`:
        
        * RegexFilter: 正则表达式过滤器
        * static_filter: 静态文件过滤器
        * url_filter: 合法 URL 过滤器
        * html_filter: 响应类型为 html 的 URL 过滤器(通过后缀判定，有一定的误判几率)
        * all_pass_filter: 全部接收过滤器
        * all_reject_filter: 全部拒绝过滤器
        
        `self.filter` 默认为 `html_filter`，如果你不需要，则可以将其设为 `None`  或 `all_pass_filter`。
        
        ## 进阶使用
        
        ### 构建自己的URL提取方式
        
        采用默认提取 URL 的方式或许无法满足你的需求，可以采用自己的方式提取 URL:
        
        ``` python
            def handle(self, response: HTMLResponse):
                # do someting
                yield from (response.url_join(a.attrs["href"]) for a in response.bs.select("a"))
        ```
        
        其中，`response.url_join` 用于将从网页中提取的原始 URL 转换为绝对 URL。例如你正在访问 `http:www.test.com/page1`，其中提取到的 URL 可能为 `link1`。此时使用 `url_join` 将其转换为 `http:www.test.com/page1/link1`。
        
        ### 自定义请求参数
        
        虽然在前面的示例中都是直接使用 URL 代表需要进行爬取的目标。但是在 `easy_spider` 中可以使用 `Request` 对象进行更细粒度的控制。例如:
        
        ```
            def handle(self, response: HTMLResponse):
                urls = [response.url_join(a.attrs["href"]) for a in response.bs.select("a")]
                for url in urls:
                    if url.startswith("you pattern"):
                        yield Request(url, cookies={"c1": "v1"})
                    else:
                        yield Request(url, cookies={"c2": "v2"})
        ```
        
        `Request` 对象可定义的参数有:
        
        ```
        method: str = 请求方法 GET|POST|PUT|DELETE 
        timeout: int = 超时时间
        headers: dict = 请求头，默认{}
        cookies: dict = cookies，默认{}
        encoding: str = 编码方式，默认utf-8
        params: dict = URL参数，默认{}
        data: dict = 数据，取决于 data_format
        data_format: str = 数据格式 FORM|JSON，若为 FORM 数据通过 application/x-www-form-urlencoded 格式传递，若为 JSON 则通过 application/json。
        ```
        handle 方法返回 str 或 Request 的迭代器都是合法的，`easy spider` 会自动判断，并生成 Request 对象。
        
        ### 默认请求参数
        
        很多时候需要定义一系列默认参数，而不是在每个请求中都声明。这样可以使用 `easy spider` 自带的 `from_url(self, url: str, use_default_params=True)` 或 `from_url_iter(self, urls: Iterable[str], use_default_params=True)`方法，该方法会在 `MySpider ` 中寻找与 `Request` 相同名称的属性，并用其构造新请求:
        
        ```python
        class MySpider(AsyncSpider):
        
            def __init__(self):
                super().__init__()
                self.start_targets = ["https://github.blog/"]
                self.cookies = {"key": "value"}  # 用于设置默认请求参数
        
            def handle(self, response: HTMLResponse):
                urls = [response.url_join(a.attrs["href"]) for a in response.bs.select("a")]
                yield self.from_url(urls)  # 所有请求的 cookies 都将设置与 self.cookies 相同
        ```
        
        ### 自定义处理方法
        
        可以通过设置 `request` 的 `handler` 属性来设置处理该 `Request` 所返回的 `Response`:
        ```python
        from easy_spider import async_env, AsyncSpider, Request, HTMLResponse
        
        class MySpider(AsyncSpider):
        
            def __init__(self):
                super().__init__()
                self.cookies = {"key": "value"}  # 用于设置默认请求参数
                self.start_targets = ["https://github.blog/"]
        
            def handle(self, response: HTMLResponse):
                urls = [response.url_join(a.attrs["href"]) for a in response.bs.select("a")]
                for url in urls:
                    if url.endswith("jpg"):
                        yield Request(url, handler=self.handle_jpg)
                    else:
                        yield Request(url, handler=self.handle)
        
            def handle_jpg(self, response):
                # do something
                pass
        
        async_env.run(MySpider())
        ```
        
        ### URL去重
        
        在 `easy spider` 中可以使用 `history_filter` 进行去重，设置:
        
        `self.filter = history_filter(html_filter, 10000, 0.001)`
        
        `history_filter` 必须依赖于其他 `filter`。`history_filter` 将其他 `filter` 接受的 URL 放入历史中，若下次再出现则拒绝该URL。`history_filter` 有三个参数:
        
        * pre_filter:  history_filter 所依赖的过滤器
        * max_elements
        * error_rate
        
         `history_filter ` 采用布隆过滤器实现去重，其中 `max_elements` 以及 `error_rate` 是与布隆过滤器相关的参数，其具体意义请参照[python-bloom-filter](https://github.com/hiway/python-bloom-filter)。
        
        
        
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Description-Content-Type: text/markdown
