爬虫学习[2]
简单的网页爬虫
使用requests库进行内容的获取
使用requests可以很方便的获取网页的源代码
import requests
url="https://www.bing.com"
source=requests.get(url).content.decode()
print(source)
使用浏览器来访问网页,看起来只需要输入网址就可以。但其实网页有很多种打开方式,最常见的是GET方式和POST方式。在浏览器里面可以直接通过输入网址访问的页面,就是使用了GET方式。还有一些页面,只能通过从另一个页面单击某个链接或者某个按钮以后跳过来,不能直接通过在浏览器输入网址访问,这种网页就是使用了POST方式
POST与GET的区别
GET
对于使用GET方式的网页,在Python里面可以使用requests的get()方法获取网页的源代码
POST
网页的访问方式除了GET方式以外,还有POST方式。有一些网页,使用GET和POST方式访问同样的网址,得到的结果是不一样的。还有另外一些网页,只能使用POST方式访问,如果使用GET方式访问,网站会直接返回错误信息。
使用原书之中的案例网址
直接访问的结果是这样的:
那么这时需要使用post方法取得数据,与get方法的主要区别是需要填一个表单,根据网页的差异,有时需要的是字典形式的数据,而有时则是json形式的数据。
import requests
data={
'key1':'value1','key2':'value2'}
formdata=requests.post('网址',data=data).content.decode()
#使用formdata提交数据
json=requests.post('网址',json=data).content.decode()
#使用json提交数据
提交后的结果:
为了充分利用带宽,需要使用多线程技术。
多线程编程
Python这门语言在设计的时候,有一个全局解释器锁(Global Interpreter Lock, GIL)。这导致Python的多线程都是伪多线程,即本质上还是一个线程,但是这个线程每个事情只做几毫秒,几毫秒以后就保存现场,换做其他事情,几毫秒后再做其他事情,一轮之后回到第一件事上,恢复现场再做几毫秒,继续换……微观上的单线程,在宏观上就像同时在做几件事。这种机制在I/O(Input/Output,输入/输出)密集型的操作上影响不大,但是在CPU计算密集型的操作上面,由于只能使用CPU的一个核,就会对性能产生非常大的影响。所以涉及计算密集型的程序,就需要使用多进程,Python的多进程不受GIL的影响。(感谢以前学的《并行计算》与《操作系统》)
爬虫属于I/O密集型的程序,所以使用多线程可以大大提高爬取效率。
什么是线程池?
线程池就是创建若干个可执行的线程放入一个池(容器)中,有任务需要处理时,会提交到线程池中的任务队列,处理完之后线程并不会被销毁,而是仍然在线程池中等待下一个任务。
多进程库
multiprocessing本身是Python的多进程库,用来处理与多进程相关的操作。但是由于进程与进程之间不能直接共享内存和堆栈资源,而且启动新的进程开销也比线程大得多,因此使用多线程来爬取比使用多进程有更多的优势。multiprocessing下面有一个dummy模块,它可以让Python的线程使用multiprocessing的各种方法。
dummy下面有一个Pool类,它用来实现线程池。这个线程池有一个map()方法,可以让线程池里面的所有线程都“同时”执行一个函数。使用的一个例子如下:
from multiprocessing.dummy import Pool
def calc_power2(num):#定义函数
return num*num
pool=Pool(3)#申明三个线程
#这3个线程负责计算10个数字的平方,谁先计算完手上的这个数,谁就先取下一个数继续计算,直到把所有的数字都计算完成为止。
ori_num=[x for x in range(1,10)]
result=pool.map(calc_power2,ori_num)#第一个参数是函数名;第二个参数是可以迭代的对象,这个对象的每一个元素都会被前者接受
print(result)
爬虫的常见搜索算法
主要分为两种:DFS与BFS
深度优先搜索
广度优先搜索
实现原书中案例 --爬取小说《动物庄园》
本次实战仅供交流学习,支持作者,请上原网站观看。
首先进行分析,这次的实际可以分为三步: