一、反扒策略
1、通过user-agent来判断是不是爬虫
解决的办法:伪装user-agent客户端标识
2、通过访问频率来判断
解决的办法:设置请求频率。time.sleep(random.randint(0,5))
3、封ip
设置代理ip。
requests.get(
url,
headers,
params,
proxies,代理字典(盛放ip)
)
proxies={
‘http’:‘http://ip:port’,
}
4、页面内容不是直接渲染,而是通过js动态加载获取
解决办法:selenium+phantomjs来解决。
二、html页面技术
1、js
html是页面骨架,css是装饰,js是页面的行为。
js非常重要。
2、jquery
js的库,作用就是简化js编程。
3、ajax
web的异步请求技术。
异步请求:
同步请求:
4、Dhtml略
三、selenium和phantomjs
1、什么是selenium
selenium是一个web自动化测试工具。但是它本身不带浏览器的功能。他这个工具其实就是可以作为一些外部应用的驱动程序一样,可以控制外部应用来完成一些任务。
2、selenium安装
pip install selenium==2.48.0
3、什么是phantomjs
phantomjs它其实就是一个内置浏览器无界面浏览器引擎。他可以像浏览器一样加载页面,运行页面中的js代码。
4、为什么selenium和phantomjs的组合可以解决任何网站的页面数据问题
selenium就像一个python程序,phantomjs就相当于一个浏览器。他们的结合就相当于用python来控制浏览器进行页面内容的解析,所以,只要能在浏览器中加载的页面,就一定能通过这个组合获取到数据。
5、phantomjs的安装
搜索phantomjs镜像,用镜像下载速度比较快。
phantomjs-2.1.1-windows.zip这个包怎么使用:在这个里面找到phantomjs.exe,将这个exe文件放到anaconda的scripts包下面。就可以不用配置环境变量了。
测试是否安装好:在cmd窗口下面输入phantomjs,如果不报错,就说明安装成功。
6.安装可视化chrome浏览器的驱动
下载安装chromedriver.exe---->这驱动就是可以让selenium驱动谷歌一个驱动。---->下载的时候一定要对照自己chrome浏览器的版本。
下载:搜索chromedriver镜像。
chromedriver_win32.zip,在里面找到chromedriver.exe,把他也放到anaconda的scripts包下面。
7、selenium的使用
# 1,导入webdriver
from selenium import webdriver
# 2,创建一个driver对象
driver = webdriver.Phantomjs()
# driver = webdriver.Chrome() # 使用谷歌浏览器
# 3.请求url
driver.get(url)
#4.等待(强制等待,建议使用显示等待)
time.sleep(2)
# 5.获取页面源码
html_str = driver.page_source
8、下面以爬取豆瓣读书的书籍信息为例,介绍selenium的使用
# 导入需要的模块
from selenium import webdriver
from lxml import etree
import time
#创建driver,使用谷歌浏览器
driver = webdriver.Chrome()
# 爬取网页内容
def get_xpath_by_selenium(url):
# 1,请求url
driver.get(url)
# 2,等待
time.sleep(3)
# 3,获取页面源码内容
html_str = driver.page_source
# 4,返回页面的element对象
return etree.HTML(html_str)
# 解析每一页,获取数据信息
def parse_page(html):
'''
获取的内容:
书名,评价数,作者出版社,价格,出版日期,评分,图片链接,详情页链接
'''
# selenium获取的页面都是js加载的页面,这种页面都有一个特点:页面虽然都是js代码,但是会放一个空
# div,将来获取到数据,就是插入到这个div中,所以我们在用xpath找数据的时候,只要从这个div开始定位
# 就一定能找到。
div_list = html.xpath('//div[@id="root"]/div/div[2]/div/div') # 使用xpath 筛选数据范围
# print(div_list)
for div in div_list:
# 书名
name = get_text(div.xpath('.//div[@class="title"]/a/text()')) #使用xpath精确查找数据
# 评价数
if name:
comment_num = get_text(div.xpath('.//span[@class="pl"]/text()'))
infos = get_text(div.xpath('.//div[@class="meta abstract"]/text()'))
# print(infos) # [美] 埃里克·马瑟斯 / 袁国忠 / 人民邮电出版社 / 2016-7-1 / 89.00元
infos = infos.split('/')
# 作者
author = infos[0]
# 出版社
publish = infos[-3]
# 价格
price = infos[-1]
# 出版日期
date = infos[-2]
# 评分
scores = get_text(div.xpath('.//span[@class="rating_nums"]/text()'))
# 图片链接
img_url = get_text(div.xpath('.//div[@class="item-root"]/a/img/@src'))
# 详情页链接
detail_url = get_text(div.xpath('.//div[@class="item-root"]/a/@href'))
item = {}
item['name'] = name
......
print(item)
# 保存数据,略
# 定义返回数据的方法
def get_text(text):
if text:
return text[0]
return ''
def main():
base_url = 'https://search.douban.com/book/subject_search?search_text=python&cat=1001&start=%s'
# 分页,爬取前10页
for i in range(10):
html = get_xpath_by_selenium(base_url%(i*15)) # 执行函数方法
parse_page(html) # 执行爬取每一页信息的方法
if __name__ == '__main__':
main()
9、将函数方法改装成类方法,使用显示等待 , 代码如下:
from selenium import webdriver
# 导入显示等待所需要的三个包
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from lxml import etree
import time
class Douban(object):
def __init__(self,url):
self.url = url
self.driver = webdriver.Chrome()
# 第一个参数,等待作用哪个driver,20为最大等待时长,20s后还没等待数据出来,就报timeout超时异常
self.wait = WebDriverWait(self.driver,20)
self.parse() # 执行爬取方法
def parse(self):
# 分页,爬取前10页
for i in range(10):
html = self.get_xpath_by_selenium(self.url % (i * 15),'//div[@id="root"]/div/div[2]/div/div') # 执行函数方法
self.parse_page(html)
def get_xpath_by_selenium(self,url,xpath):
# 1,请求url
self.driver.get(url)
# 2,强制等待,不建议使用
# time.sleep(3)
# 显示等待:By.XPATH,定位的选择器的名称,元组的第二个参数是定位器,即数据的位置。
self.wait.until(EC.presence_of_all_elements_located((By.XPATH,xpath)))
# 3,获取页面内容
html_str = self.driver.page_source
# 4,返回页面的element对象
return etree.HTML(html_str)
def get_text(self,text):
if text:
return text[0]
return ''
def parse_page(self,html):
'''
获取的内容:
书名,评价数,作者出版社,价格,出版日期,评分,图片链接,详情页链接
'''
div_list = html.xpath('//div[@id="root"]/div/div[2]/div/div')
# print(div_list)
for div in div_list:
# 书名
name = self.get_text(div.xpath('.//div[@class="title"]/a/text()'))
# 评价数
if name:
comment_num = self.get_text(div.xpath('.//span[@class="pl"]/text()'))
infos = self.get_text(div.xpath('.//div[@class="meta abstract"]/text()'))
#print(infos)#[美] 埃里克·马瑟斯 / 袁国忠 / 人民邮电出版社 / 2016-7-1 / 89.00元
infos = infos.split('/')
# 作者
author = infos[0]
# 出版社
publish = infos[-3]
# 价格
price = infos[-1]
# 出版日期
date = infos[-2]
# 评分
scores = self.get_text(div.xpath('.//span[@class="rating_nums"]/text()'))
# 图片链接
img_url = self.get_text(div.xpath('.//div[@class="item-root"]/a/img/@src'))
# 详情页链接
detail_url = self.get_text(div.xpath('.//div[@class="item-root"]/a/@href'))
item = {}
item['name'] = name
.....
print(item)
if __name__ == '__main__':
base_url = 'https://search.douban.com/book/subject_search?search_text=python&cat=1001&start=%s'
Douban(base_url) # 实例化对象,传入url