本来想爬六维空间(http://bt.neu6.edu.cn/)的搞笑图片来着。。。不知道为啥这两天上不去了。。。
于是就拿品知人大试一下python的这两个库。
用到的lxml函数可以参考:http://lxml.de/api/lxml.html.HtmlElement-class.html
主要的思路就是利用urllib获取网址内容,利用lxml解析特定规则的url。
要爬取的网页起始地址是:http://bt.ruc6.edu.cn/b/forum-36-1.html
一般写一个有递归逻辑的程序时,我喜欢先从最小的可以完成的单位写起。
那么,第一步,先点开一页,找一个图片的url,试一下能不能爬下来。
正好看到有一个我校『大白』的帖子(http://bt.ruc6.edu.cn/b/thread-222560-1-1.html)。ps:大白是学校里的一只流浪猫,据学校的流浪动物之家发的消息看,大白应该是3月初左右被中关村的一位漂亮的 IT MM 收养了。
第一张大白图片地址:http://bt.ruc6.edu.cn/b/data/attachment/forum/201604/14/215736wyrrrip32633fiaf.jpg
代码:
def get_page_string(url): # 因为获取网页字符串比较常用,所以就单独写成一个函数。
return urllib.urlopen(url).read()
def save_img(url):
file_name = url.split('/')[-1] # 直接用网页上的图片名作为保存到本地的图片名
if os.path.exists('pic/' + file_name):
pass
else:
with open('pic/' + file_name, 'w') as of:
of.write(get_page_string(url))
第二步,找到这一页的想要爬取图片的url。
首先看一下,这几幅图片的xml路径
//*[@id="aimg_270475"]
//*[@id="aimg_270474"]
//*[@id="aimg_270473"]
。。。
看起来挺有规律的样子。不过,因为不知道其它的网页中的图片的id是怎么个样子,直接用id来爬并不好。
观察一下,发现这一页的所有图片都在标签是『td』中,而且其class属性是『t_f』。随便打开一个其它的网页也是这样的。那就暂时用这个线索来查找图片。
def iter_img(url):
try:
print get_page_string(url)
doc = lxml.html.document_fromstring(get_page_string(url)) # 从网页的字符串中得到一个基本的HtmlElment,用于调用lxml提供的函数。
element_class = doc.find_class('t_f')[0]# 这个返回的是一个数组,为了方便,只留第一个就行了。
imgs = element_class.findall('.//img') # 找到这个路径下面所有的,标签是img的元素。
for img in imgs:
print img.attrib['src'] # 打印出属性为『src』的内容
except:
pass # 有时候请求不到就算了。。
试了一下,竟然没有返回结果。是网页保存到本地,再通过JS动态加载内容的吗?
那只好用selenium里面的WebDriverWait函数,等网页加载好了再解析喽。。
对于mac和linux的操作系统,要有一个Chromedriver。 在 http://download.csdn.net/detail/hooo/7819273 上下载。然后放到 /usr/local/bin/ 下。并将其权限改成可执行。
selenium里面的一些函数与lxml细节上有些出入,但整体思想并没有什么变化。用的时候,到它官网上找一下函数说明即可。
def iter_img_page(pageURL):
driver = Chrome() # 调用浏览器
driver.get(pageURL)
WebDriverWait(driver, 100).until(lambda x: x.find_element_by_xpath('.//ignore_js_op'))
imgs = driver.find_elements_by_xpath('.//ignore_js_op/img') # 找到相应的标签。
for img in imgs:
img_url = img.get_attribute('src')# 打印出属性为『src』的内容
print img_url
save_img(img_url)
个人感觉,因为现在的框架实在是太多,一个人没必要也没那么多的时间去学。只要用的时候知道哪里去找就行了。
这次测试的完整代码如下:
#!/usr/bin/python
# -*- coding:utf-8 -*-
# Author: [email protected]
# This python program is used to draw pictures from bt.ruc6.edu.cn
import lxml.html # 用于解析html
import os
from selenium.webdriver import Chrome
from selenium.webdriver.support.ui import WebDriverWait
import urllib # 用于抓取网页内容
rootURL = 'http://bt.ruc6.edu.cn/b/forum-36-1.html'
dabaiURL = 'http://bt.ruc6.edu.cn/b/data/attachment/forum/201604/14/215736wyrrrip32633fiaf.jpg'
dabaiPageURL = 'http://bt.ruc6.edu.cn/b/thread-222560-1-1.html'
def get_page_string(url): # 因为获取网页字符串比较常用,所以就单独写成一个函数。
return urllib.urlopen(url).read()
def save_img(url):
file_name = url.split('/')[-1] # 直接用网页上的图片名作为保存到本地的图片名
if os.path.exists('pic/' + file_name): # 把图片放到本目录的'pic'文件夹下
pass # 要是文件存在就不处理了。
else:
print 'saving', url
with open('pic/' + file_name, 'w') as of:
of.write(get_page_string(url))
def iter_img(url): # 因为网页内容不是一次返回到客户端,所以这个函数就没用到。
try:
print get_page_string(url)
doc = lxml.html.document_fromstring(get_page_string(url)) # 从网页的字符串中得到一个基本的HtmlElment,用于调用lxml提供的函数。
element_class = doc.find_class('t_f')[0]# 这个返回的是一个数组,为了方便,只留第一个就行了。
imgs = element_class.findall('.//img') # 找到这个路径下面所有的,标签是img的元素。
for img in imgs:
print img.attrib['src'] # 打印出属性为『src』的内容
except:
pass # 有时候请求不到就算了。。
def iter_img_page(pageURL):
driver = Chrome() # 调用浏览器
driver.get(pageURL)
WebDriverWait(driver, 100).until(lambda x: x.find_element_by_xpath('.//ignore_js_op'))
imgs = driver.find_elements_by_xpath('.//ignore_js_op/img') # 找到相应的标签。
for img in imgs:
img_url = img.get_attribute('src')# 打印出属性为『src』的内容
print img_url
save_img(img_url)
if __name__ == '__main__':
# save_img(dabaiURL)
iter_img_page(dabaiPageURL)
附大白照片