首先来张图:
将就看吧,我都有点不好意思,但至少表现出来要表达的意思了,我们最终要获得的信息不是在第一个页面中,而是从第一个页面中进入第二个页面,需要的信息在第二个页面中,虽然电影列表有很多页,但是现阶段都不考虑只获取第一页中的所有电影的下载连接。
这个爬虫分三步
- 先从第一页中将所有第二页的url取出来,存到列表中
- 循环第二页地址的列表,将这个url与网站域名拼凑成真正地址,然后获取第二页的代码
- 从第二页代码中获取最终需要的下载地址存储到一个字典中
首先利用bs4从第一页中获取所有第二页的url,并存储到一个列表中:
|
|
上面的encoding = chardet.detect(content)[‘encoding’]是探测网页编码比如utf-8,gbk
因为python的内部编码为unicode,所以需要将获取到的内容转换为unicode,上句话已经获得到了网页的编码,下面这句话就是转换了,content = content.decode(encoding, ‘ignore’)这句代码为什么要加ignore,那我下面就要引用了
比如,若要将某个String对象s从gbk转换为unicode,可以如下操作
s.decode(‘gbk’)
可是,在实际开发中,我发现,这种办法经常会出现异常:
UnicodeDecodeError: ‘gbk’ codec can’t decode bytes in position 30664-30665: illegal multibyte sequence这是因为遇到了非法字符——尤其是在某些用C/C++编写的程序中,全角空格往往有多种不同的实现方式,比如\xa3\xa0,或者\xa4\x57,这些 字符,看起来都是全角空格,但它们并不是“合法”的全角空格(真正的全角空格是\xa1\xa1),因此在转码的过程中出现了异常。
这样的问题很让人头疼,因为只要字符串中出现了一个非法字符,整个字符串——有时候,就是整篇文章——就都无法转码。
解决办法:s.decode(‘gbk’, ‘ignore’)
因为decode的函数原型是decode([encoding], [errors=’strict’]),可以用第二个参数控制错误处理的策略,默认的参数就是strict,代表遇到非法字符时抛出异常;
如果设置为ignore,则会忽略非法字符;
如果设置为replace,则会用?取代非法字符;
如果设置为xmlcharrefreplace,则使用XML的字符引用。
经过上面的处理,所有第二页的url就存储到了films_set列表中了,下一步需要循环这个列表将所有的url与域名拼凑起来形成最终的url
|
|
因为最终第二页的url已经拿到,那么我们接下来就去获取第二页的源码,分析然后拿到电影下载地址。
|
|
在这又遇到个问题,就是在浏览器中用f12看到的下载地址的td标签和用代码获取出来的td标签内容不一样,也是经过询问才知道浏览器中看到的代码是经过js处理过的,我们用代码获得的是没有经过处理的,所以这就需要调试技巧了,先在获取存储下载地址的td标签下断点,然后分析这个td标签的内容,如下:
|
|
其实我们需要的就是这个href中的内容,拿到后存储到film_dic这个字典中。我们除了拿到下载地址还需要电影的名称,这个名称是没有经过处理的,所以直接去分析源码,然后取出来并存储就行了。
以上功能都是在一个函数中实现的,下面需要调用这个函数:
|
|
以下是运行结果:
|
|
github地址:https://github.com/lowkeynic4/crawl/blob/master/dianyingtiantang.py