python之(urllib、urllib2、lxml、Selenium+PhantomJS)爬虫
一、最近在学习网络爬虫的东西,说实话,没有怎么写过爬虫,Java里面使用的爬虫也没有怎么用过。这里主要是学习Python的时候,了解到Python爬虫的强大,和代码的简介,这里会简单的从入门看是说起,主要是了解基本的开发思路,后续会讲到scrapy框架的使用,这里主要是讲Python的爬虫入门。
二、urllib、urllib2,这两个模块都是用来处理url请求的,这里的开始就是使用urllib和urllib2的库进行相关操作,来看一个例子:
#!/usr/bin/env python # -*- coding:utf-8 -*- import urllib import urllib2 # 需要爬取的连接 url = "http://www.baidu.com" # 模拟的浏览器 headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"} # 表单数据 form_data = { "start": "0", "end": "20" } # 编码 data = urllib.urlencode(form_data) # 设定请求 request = urllib2.Request(url, data=data, headers=headers) # 访问获取结果 html = urllib2.urlopen(request).read() print html
说明:这里获取结果的方式,是通过代码去模拟浏览器,来达到访问的目的。这里的form_data 只是一个模拟ajax的请求,没有太大的用处。
注意:urllib2.Request中如果存在data数据则是POST请求,反之GET
三、上面我们获取到了结果,接下来就是解析,lxml是常用的一中解析方式,当然还存在其他解析的方式比如re,这里不详细介绍:
1)在说解析之前,讲一下urllib2的handler:
a、handler种类:handler分很多种,比如:cookie,proxy,auth、http等。
b、为什么使用handler:cookie处理回话的保存问题;proxy处理ip代理,访问ip被封;auth认证处理;http处理器相关方式;
c、处理器比较常见,在会话或者代理都有很好的应用
#!/usr/bin/env python # -*- coding:utf-8 -*- import urllib import urllib2 import cookielib # 通过CookieJar()类构建一个cookieJar()对象,用来保存cookie的值 cookie = cookielib.CookieJar() # 通过HTTPCookieProcessor()处理器类构建一个处理器对象,用来处理cookie # 参数就是构建的CookieJar()对象 cookie_handler = urllib2.HTTPCookieProcessor(cookie) # 代理handler # httpproxy_handler = urllib2.ProxyHandler({"http" : "ip:port"}) # 认证代理handler # authproxy_handler = urllib2.ProxyHandler({"http" : "username:password@ip:port"}) # auth # passwordMgr = urllib2.HTTPPasswordMgrWithDefaultRealm() # passwordMgr.add_password(None, ip, username, password) # httpauth_handler = urllib2.HTTPBasicAuthHandler(passwordMgr) # proxyauth_handler = urllib2.ProxyBasicAuthHandler(passwordMgr) # opener = urllib2.build_opener(httpauth_handler, proxyauth_handler) # 构建一个自定义的opener opener = urllib2.build_opener(cookie_handler) # 通过自定义opener的addheaders的参数,可以添加HTTP报头参数 opener.addheaders = [("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36")] # renren网的登录接口 url = "http://www.renren.com/PLogin.do" # 需要登录的账户密码 data = {"email":"邮箱", "password":"密码"} # 通过urlencode()编码转换 data = urllib.urlencode(data) # 第一次是post请求,发送登录需要的参数,获取cookie request = urllib2.Request(url, data = data) # 发送第一次的post请求,生成登录后的cookie(如果登录成功的话) response = opener.open(request) #print response.read() # 第二次可以是get请求,这个请求将保存生成cookie一并发到web服务器,服务器会验证cookie通过 response_deng = opener.open("http://www.renren.com/410043129/profile") # 获取登录后才能访问的页面信息 html = response_deng.read() print html
2)解析(lxml):
# !/usr/bin/python # -*- coding: UTF-8 -*- import urllib2 from lxml import etree if __name__ == '__main__': # url = raw_input("请输入需要爬取图片的链接地址:") url = "https://www.baidu.com" headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"} # 读取到的页面 html = urllib2.urlopen(url).read() # 使用lxml的etree content = etree.HTML(html) # XPATH的写法 img_list = content.xpath("//img/@src") # 对图片连接处理 for link in img_list: try: if link.find("https") == -1: link = "https:" + link img = urllib2.urlopen(link).read() str_list = link.split("/") file_name = str_list[len(str_list) - 1] with open(file_name, "wb") as f: f.write(img) except Exception as err: print err
xpath的语法参考:http://www.w3school.com.cn/xpath/xpath_syntax.asp
3)另外一种使用方式(BeautifulSoup):
# !/usr/bin/python # -*- coding: UTF-8 -*- import urllib2 from bs4 import BeautifulSoupif __name__ == '__main__': url = "https://tieba.baidu.com/index.html" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"} # 读取到的页面 html = urllib2.urlopen(url).read() bs = BeautifulSoup(html, "lxml") img_list = bs.find_all("img", attrs={"class": ""}) # 对图片连接处理 for img in img_list: try: link = img.get("src") if link.find("https") == -1: link = "https:" + link img = urllib2.urlopen(link).read() str_list = link.split("/") file_name = str_list[len(str_list) - 1] with open(file_name, "wb") as f: f.write(img) except Exception as err: print err
四、Selenium+PhantomJS,上面的都是针对于静态的html文件进行的爬虫,但是现在的网站一般都是通过ajax动态的加载数据,这里就产生了一个问题,我们必须先把js加载完成,才能进行下一步的爬虫工作。这里也就产生了对应的框架,来做这一块的爬虫工作。
from selenium import webdriver from bs4 import BeautifulSoup if __name__ == '__main__': # 使用谷歌的浏览器 driver = webdriver.Chrome() # 获取页面 driver.get("https://www.douyu.com/directory/all") while True: # 确认解析方式 bs = BeautifulSoup(driver.page_source, "lxml") # 找到对应的直播间名称 title_list = bs.find_all("h3", attrs={"class": "DyListCover-intro"}) # 直播间热度 hot_list = bs.find_all("span", attrs={"class": "DyListCover-hot"}) # 压缩成一个循环 for title, hot in zip(title_list, hot_list): print title.text, hot.text # 执行下一页 if driver.page_source.find("dy-Pagination-next") == -1: break driver.find_element_by_class_name("dy-Pagination-next").click() # 退出 driver.quit()
备注:我这里使用的是chrome的浏览器来执行的操作,目前因为PhantomJS已经被放弃了,不建议使用
chromedriver.exe的下载需要到谷歌网站上下载(需要FQ),我这里提供一个75版本的下载
淘宝镜像下载地址:https://npm.taobao.org/mirrors/chromedriver/
下面提供一种针对于图片后加载的处理:
import urllib2 import time from selenium import webdriver if __name__ == '__main__': # 使用谷歌的浏览器driver,需要chromedriver.exe支持(放在文件同目录下) # 项目运行时记得让浏览器全屏 driver = webdriver.Chrome() # 爬取网址 driver.get("https://www.douyu.com/directory/all") while True: # 下一页后等待加载 time.sleep(2) # 屏幕滚动(这里的值,更具具体页面设置) for i in xrange(1, 11): js = "document.documentElement.scrollTop=%d" % (i * 1000) driver.execute_script(js) # 等待页面加载完成 time.sleep(1) # 获取页面的图片(xpath方式) img_list = driver.find_elements_by_xpath("//div[@class='LazyLoad is-visible DyImg DyListCover-pic']/img") # 对图片连接处理 for img in img_list: try: link = img.get_attribute("src") str_list = link.split("/") file_name = str_list[len(str_list) - 2] print file_name # 读取图片,写入本地 img_data = urllib2.urlopen(link).read() with open("img/" + file_name, "wb") as f: f.write(img_data) except Exception as err: print err # 查看是否存在下一页 if driver.page_source.find("dy-Pagination-next") == -1: break # 如果存在则跳转至下一页 driver.find_element_by_class_name("dy-Pagination-next").click() # 退出 driver.close()
说明:这里只是针对斗鱼的图片进行的爬虫,其他页面需要进一步修改,好了js的处理包括页面需要爬取的图片基本上就是这样了。
该代码只是用于学习和尝试,不得用于其他作用
五、好了这基本上,算的上入门了吧,当然你要爬取一个完整的东西,还是需要很多功夫的,我这里只是介绍基本上常用的一些库,和我自己测试使用的一些代码,以及目前涉及的不懂的地方,仅供学习吧,有什么错误的地方还请指出。我好及时改正!!