前言:

最近在学习Python网络爬虫,在这里分享一下自己的学习成果,通过几个函数梳理下网络爬虫的过程,网络爬虫就是用自己的电脑去web服务器(另一台电脑)上下载东西,其中涉及到两个问题:

(1)怎么让自己的电脑和web服务器连接

(2)正常连接之后,怎么把想要的信息提取出来

爬虫相关函数:

def get_html_text(url): #解决第一个问题

pass

def get_info_list(html): #解决第二个问题

pass

def print_info_list(info_list): #def download_info_list(info_list):

pass

接下来,就让我们围绕这两个问题和三个函数,去看看Python是怎么解决的。

示例代码:列举了6个实际的爬虫例子(基本只用到上面三个函数)

requests获取html:

我们想要的资源,比如文字、图片等,其实都在html里面。一个网页的url,对应一个html,我们可以通过requests库,轻松地和服务器上的url建立连接,得到html信息。通过Response对象的status_code、text、encoding、content等方法,查看这次连接的情况如何。

def get_html_text(url):

try:

r = requests.get(url, timeout=30)

r.raise_for_status

r.encoding = r.apparent_encoding

return r.text

except:

return "requests error"

但是,该函数返回的是一个str类型的html,这是非常不方便我们获取信息的

BeautifulSoup解析html:

html页面得到了,我们的爬虫就完成了一半了。。。哈哈,开玩笑的,其实爬虫最难的地方就在定位信息,特别是定位大量信息的时候。不过不着急,BeautifulSoup很好地帮我们解决了这个问题。它可以解析我们通过requests获得的str类型的html,使其成为一个真正的html,我们可以通过标签的属性或名称去定位标签,可以定位标签之后,获取信息就方便多了。

def get_info_list(html):

"""

获取目标图片的url链接

"""

soup = BeautifulSoup(html,"html.parser")

img_tags = soup.find_all("noscript")

img_urls = []

for tag in img_tags:

try:

img_urls.append(re.findall(r'src=".*?"',tag.get_text())[0][5:-1])

except:

continue

return img_urls

在上面的代码中,除了用标签名字定位标签外,还使用了正则表达式来辅助我们找到想要的信息。上图可以看出,图片url在src属性上,可以愉快地下载小姐姐的美照了。

值得注意的是,定位标签是网络爬虫中很重要的一件事,我给出的几个爬虫demo中都有体现。通过要找的信息,到跟信息相关的标签,再到标签之间的逻辑关系,都值得我们仔细思考。选取哪个标签,才能通过一次遍历就可以得到我们想要的所有的信息,而且还没有冗余信息呢?

再举一个例子说明这个问题

def get_info_list(html):

ulist = []

soup = BeautifulSoup(html,'html.parser')

for tr in soup.find('tbody').children:

if isinstance(tr,bs4.element.Tag):

tds = tr.find_all('td')

ulist.append([tds[0].string,tds[1].string,tds[2].string])

return ulist

这个例子是爬取中国大学的排名信息,从图中可以看出所有大学的信息都在tbody一个标签里,而tbody有好多子标签tr,每一个tr存储的是一个学校的各种信息,那么逻辑就很清楚了,只要遍历tbody的每一个子标签tr,就可以通过一个循环,得到我们想要的所有信息了。

print or download?

接下来的事就比较简单了,数据量较少可以选择打印出来,数据如果是图片等二进制文件可以选择下载到本地

def print_info_list(ulist,num):

tplt = '{0:^10}\t{1:{3}^10}\t{2:^10}\t'

print(tplt.format('排名','学校名称','省份',chr(12288)))

for i in range(num):

u = ulist[i]

print(tplt.format(u[0],u[1],u[2],chr(12288)))

def download_imgs(img_urls):

start_name = 0

root = "./images001/"

for url in img_urls:

if not os.path.exists(root):

os.mkdir(root)

path = root + str(start_name) + ".jpg"

r = requests.get(url)

with open(path, "wb") as f:

f.write(r.content)

start_name += 1

进阶:

在爬取Github Python Trending和知乎图片的时候,涉及到几个有趣的问题:

(1)在爬取到一个url的时候,我们可以通过python命令的方式打开这个链接,而不需要手动打开,是不是很酷呢,通过webbrowser.open就可以实现。

(2)爬取网页的时候,我们可能需要模拟鼠标滑动的操作,来获取更多信息,这个时候需要用到selenium,来自动运行JS脚本,完成鼠标滑动的操作

展望:

(1)在与web服务器连接的时候,公司肯定会设置很多障碍(robots协议等)。因为如果让别人无限制爬虫的话,对公司的网站是有很大影响的。在以后的学习里,反爬技巧和分布式爬虫(框架如Scrapy等)是我们要研究的,从而可以更好更快的爬取想要的信息

(2)在与网页的交互中,会涉及到大量的JS函数,要想爬虫更加顺利,对JS函数要很熟悉

(3)数据的存储问题,数据量大的话,肯定要存在数据库里里的