上一篇文章实现的最简单的爬虫,抓取了某个连接下第一次加载的全部图片连接。由于存在下拉刷新, 所以怎么得到该页面的所有答案是这篇文章须要去处理的事情。css
这里选择使用方案2,方案1后面遇到再讨论。html
一:selenium的简单使用。 这里涉及selenium的安装,Selenium with Python官方文档讲解的特别简单。我使用的的chrome(能够配置无头属性)。 注意:须要将下载的driver配置环境变量,以即可以访问。python
if __name__ == '__main__':
options = webdriver.ChromeOptions()
options.add_argument('headless')
# driver = webdriver.Chrome(options=options)
driver = webdriver.Chrome()
driver.implicitly_wait(2)
driver.get("https://www.zhihu.com/question/22856657")
time.sleep(2)
resSoup = BeautifulSoup(driver.page_source, 'lxml')
items = resSoup.select("figure > span > div")
print(len(items))
for item in items:
print(item)
#driver.close()
复制代码
在项目执行代码能够看到输出:python zhihu/spiders/zhihu.py
git
data-src
属性便可得图片连接。 代码解释: 前三行用于启动一个无头的driver。若是须要查看加载的状况,只用第四行代码便可,执行完毕能够查看浏览器打开的url, 以下。
接下来三行: 第一行启动driver的隐式等待,简单意思就是:2秒内网页加载完毕就往下执行,不然就加载完2秒,继续往下执行。 第二行用于打开连接,至关于手动在地址栏输入连接。 第三行延时,等待网页加载。 后面的内容前面有接触。 若是输出结果和个人相差不大,那么继续下一步。github
二:selenium执行js代码,加载所有内容。web
if __name__ == '__main__':
options = webdriver.ChromeOptions()
options.add_argument('headless')
# driver = webdriver.Chrome(options=options)
driver = webdriver.Chrome()
driver.implicitly_wait(2)
driver.get("https://www.zhihu.com/question/22856657")
time.sleep(2)
count = 1
css_selector = "#root > div > main > div > div.Question-main > div.Question-mainColumn > div > div.Card > button"
css_selector2 = "#root > div > main > div > div.Question-main > div.Question-mainColumn > div > div.CollapsedAnswers-bar"
while len(driver.find_elements_by_css_selector(css_selector)) == 0 and \
len(driver.find_elements_by_css_selector(css_selector2)) == 0:
print("count:" + str(count))
js = "var q=document.documentElement.scrollTop=" + str(count * 200000)
count += 1
driver.execute_script(js)
time.sleep(0.5)
resSoup = BeautifulSoup(driver.page_source, 'lxml')
items = resSoup.select("figure > span > div")
print(len(items))
for item in items:
print(item)
复制代码
用一个循环去执行js代码,简单意思是滑动到距离页面顶部x的距离。通过测试,200000/页是比较好的选择。chrome
至此,能够抓取某个连接下的全部图片。浏览器
三: selenium与spider middlewares的结合。 上面一切顺利以后, 接下来去使双方结合。 关于scrapy 的下载中间键(DOWNLOADER_MIDDLEWARES): 简单来讲,该中间键就是调用process_request, 将获取url的request通过处理,返回request,response,None三值之一。 返回 request:继续执行后面的process_request方法(包括中间键) response:不知行后面的process_request方法,以此response结果直接返回,执行zhihu/spiders/zhihu.py 的回调方法。 具体请看官方文档: https://docs.scrapy.org/en/latest/topics/downloader-middleware.html (还有spider middlewares, 本次未用到) bash
话很少说,开始写代码: 在middlewares.py中定义本身的中间键:服务器
class PhantomJSMiddleware(object):
def __init__(self):
options = webdriver.ChromeOptions()
options.add_argument('headless')
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(1)
def process_request(self, request, spider):
print(request.url)
driver = self.nextPage(request)
return HtmlResponse(url=request.url, body=driver.page_source, encoding="utf-8")
# 翻页操做
def nextPage(self, request):
self.driver.get(request.url)
time.sleep(2)
count = 1
css_selector = "#root > div > main > div > div.Question-main > div.Question-mainColumn > div > div.Card > button"
css_selector2 = "#root > div > main > div > div.Question-main > div.Question-mainColumn > div > div.CollapsedAnswers-bar"
# css_selector = "div > a > img"
# print(len(self.driver.find_elements_by_css_selector(css_selector)))
while len(self.driver.find_elements_by_css_selector(css_selector)) == 0 and len(
self.driver.find_elements_by_css_selector(css_selector2)) == 0:
print("count:" + str(count))
js = "var q=document.documentElement.scrollTop=" + str(count * 200000)
count += 1
self.driver.execute_script(js)
time.sleep(0.5)
print(count)
time.sleep(2)
return self.driver
@classmethod
# 信号的使用
def from_crawler(cls, crawler):
print("from_crawler")
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_closed)
return s
def spider_opened(self, spider):
print("spider close")
self.driver.close()
复制代码
稍做解释: __init__
函数作初始化工做, nextPage
函数根据获得的request作翻页操做。 **process_request
**函数是中间键的必要函数, 启动中间键以后,yield生成器中的request都会通过该函数,而后返回结果(必定要在此函数执行return)。
后面是spiders信号的使用实例, 用于在spiders执行结束的时候作处理工做,好比关闭driver等操做。
setttings.py:配置对下载中间键的使用。
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
'zhihu.middlewares.PhantomJSMiddleware': 100,
}
复制代码
以上配置完毕,便可执行爬虫。 命令行执行 scrapy crawl zhihu
启动爬虫,注意看日志,有以下输出。
下拉刷新根据网速决定,因此count值会有不一样。 能够看到这里抓取到了660张图片连接(容许个别偏差)。
至此,对于使用scrapy结合selnium抓取动态网页已经不是问题。
对于某些须要登陆的连接,打开url以后会直接去到登陆页。下一篇文章介绍怎么使用selenium 去登陆,保存cookies, 带着cookies去请求(多是万能的登陆方法,对于图片验证, 手机验证码也可能适用)。
微信:youquwen1226 github:https://github.com/yunshuipiao 欢迎来信一块儿探讨。