考虑到我们不仅要爬取列表页,还要爬取详情页,所以在这里我们定义一个较通用的爬取页面的方法,叫做 scrape_page,它接收一个 url 参数,返回页面的 html 代码 。这里首先判断了状态码是不是 200,如果是,则直接返回页面的 HTML 代码,如果不是,则会输出错误日志信息 。另外这里实现了 requests 的异常处理,如果出现了爬取异常,则会输出对应的错误日志信息,我们将 logging 的 error 方法的 exc_info 参数设置为 True 则可以打印出 Traceback 错误堆栈信息 。
好了,有了 scrape_page 方法之后,我们给这个方法传入一个 url,正常情况下它就可以返回页面的 HTML 代码了 。
接着在这个基础上,我们来定义列表页的爬取方法吧,实现如下:
def scrape_index(page): index_url = f\'{BASE_URL}/page/{page}\' return scrape_page(index_url)
方法名称叫做 scrape_index,这个实现就很简单了,这个方法会接收一个 page 参数,即列表页的页码,我们在方法里面实现列表页的 URL 拼接,然后调用 scrape_page 方法爬取即可,这样就能得到列表页的 HTML 代码了 。
获取了 HTML 代码之后,下一步就是解析列表页,并得到每部电影的详情页的 URL 了,实现如下:
def parse_index(html): pattern = re.compile(\'<a.*?href=https://www.fajihao.com/"(.*?)\".*?>\') items = re.findall(pattern, html) if not items: return [] for item in items: detail_url = urljoin(BASE_URL, item) logging.info(\'get detail url %s\', detail_url) yield detail_url
在这里我们定义了 parse_index 方法,它接收一个 html 参数,即列表页的 HTML 代码 。
在 parse_index 方法里面,我们首先定义了一个提取标题超链接 href 属性的正则表达式,内容为:
<a.*?href=https://www.fajihao.com/"(.*?)\".*?>
在这里我们使用非贪婪通用匹配正则表达式 .*? 来匹配任意字符,同时在 href 属性的引号之间使用了分组匹配 (.*?) 正则表达式,这样 href 的属性值我们便能在匹配结果里面获取到了 。紧接着,正则表达式后面紧跟了 来标示这个 <a> 节点是代表电影名称的节点 。
好,现在有了正则表达式,那么怎么提取列表页所有的 href 值呢?使用 re 的 findall 方法就好了,第一个参数传入这个正则表达式构造的 pattern 对象,第二个参数传入 html,这样 findall 方法便会搜索 html 中所有能匹配该正则表达式的内容,然后把匹配到的结果返回,最后赋值为 items 。
如果 items 为空,那么我们可以直接返回空的列表,如果 items 不为空,那么我们直接遍历处理即可 。
遍历 items 得到的 item 就是我们在上文所说的类似 /detail/1 这样的结果 。由于这并不是一个完整的 URL,所以我们需要借助 urljoin 方法把 BASE_URL 和 href 拼接起来,获得详情页的完整 URL,得到的结果就类似 https://ssr1.scrape.center/detail/1 这样的完整的 URL 了,最后 yield 返回即可 。
这样我们通过调用 parse_index 方法并传入列表页的 HTML 代码就可以获得该列表页所有电影的详情页 URL 了 。
好,接下来我们把上面的方法串联调用一下,实现如下:
def main(): for page in range(1, TOTAL_PAGE + 1): index_html = scrape_index(page) detail_urls = parse_index(index_html) logging.info(\'detail urls %s\', list(detail_urls))if __name__ == \'__main__\': main()
这里我们定义了 main 方法来完成上面所有方法的调用,首先使用 range 方法遍历了一下页码,得到的 page 就是 1-10,接着把 page 变量传给 scrape_index 方法,得到列表页的 HTML,赋值为 index_html 变量 。接下来再将 index_html 变量传给 parse_index 方法,得到列表页所有电影的详情页 URL,赋值为 detail_urls,结果是一个生成器,我们调用 list 方法就可以将其输出出来 。
好,我们运行一下上面的代码,结果如下:
2020-03-08 22:39:50,505 - INFO: scraping https://ssr1.scrape.center/page/1...2020-03-08 22:39:51,949 - INFO: get detail url https://ssr1.scrape.center/detail/12020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/22020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/32020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/42020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/52020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/62020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/72020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/82020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/92020-03-08 22:39:51,950 - INFO: get detail url https://ssr1.scrape.center/detail/102020-03-08 22:39:51,951 - INFO: detail urls [\'https://ssr1.scrape.center/detail/1\', \'https://ssr1.scrape.center/detail/2\', \'https://ssr1.scrape.center/detail/3\', \'https://ssr1.scrape.center/detail/4\', \'https://ssr1.scrape.center/detail/5\', \'https://ssr1.scrape.center/detail/6\', \'https://ssr1.scrape.center/detail/7\', \'https://ssr1.scrape.center/detail/8\', \'https://ssr1.scrape.center/detail/9\', \'https://ssr1.scrape.center/detail/10\']2020-03-08 22:39:51,951 - INFO: scraping https://ssr1.scrape.center/page/2...2020-03-08 22:39:52,842 - INFO: get detail url https://ssr1.scrape.center/detail/112020-03-08 22:39:52,842 - INFO: get detail url https://ssr1.scrape.center/detail/12...
- 双11尾款满减包含定金的钱吗 2022年双11预售合并支付尾款参加满减吗
- 双11买黄金会比平时买便宜多少 2022年双11买黄金划算吗
- iPad10和新款iPadPro为什么涨价 iPad全线大涨价了吗2022
- 得物一般哪些节日打折 2022得物双十一有活动吗
- 得物双十一优惠力度有多大 2022年得物双十一所有鞋会降价吗
- 得物双十一优惠力度有多大 得物双十一什么时候开始2022
- 老人为啥说窗帘不用蓝色 2022年窗帘流行纯色还是拼色
- 用了一年多的72v电动车能跑多远 72伏电动车能跑多少公里
- ps cs6是哪年的版本 pscs6是最新版本吗
- 2021年倒闭的品牌 2021年315晚会曝光品牌