笔者最近在学习Python网络爬虫技术,接触了一些常用的库和框架,也尝试了多种场景。其中,爬取Ajax页面信息是相对比较麻烦的一个问题,而Selenium框架为这类问题提供了相对通用且易于操作的解决方案。这里分享一个分页爬取百度图片搜索结果的案例,希望对有需要的同学有所帮助。
话不多说,先上代码:
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
import re
import time
import requests
import html
def getpageshtml(pagenum,wd):
'''通过selenium获取滚动后的页面HTML'''
#创建chrome浏览器
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
browser = webdriver.Chrome(chrome_options=chrome_options)
#加载百度图片信息
try:
url = 'http://image.baidu.com/search/index?tn=baiduimage&word=' + wd
browser.get(url)
#滚动条向下滚动
js = 'var q=document.documentElement.scrollTop=10000'
for i in range(pagenum - 1):
time.sleep(2)
browser.execute_script(js)
#获取HTML
pagehtml = browser.page_source
browser.close()
#下载图片
downpics(pagehtml)
except TimeoutException:
getpageshtml(pagenum,wd)
def downpics(pagehtml):
'''下载图片'''
#正则获取图片URL
plist = re.findall('" data-objurl="(.*?)[\?,"]',pagehtml)
#循环下载
uheader = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36'}
i = 0
for src in plist:
i = i + 1
print('正在下载: %d / %d' %(i,len(plist)))
try:
#获取图片
r = requests.get(url=src,headers=uheader,timeout=5)
#生成本地文件名
filename = './pic/%s %s' %(str(i),src[src.rfind('/')+1:])
filename = html.unescape(filename)
if int(filename.rfind('.')) <= 0:
filename = filename + '.jpg'
#写文件到本地
with open(filename, 'wb') as f:
f.write(r.content)
except Exception as err:
print(err)
continue
#程序入口
if __name__ == '__main__':
print('='*20,'百度图片爬虫','='*20)
keyword = input('请输入图片关键词:')
pagenum = input('请输入抓取页数:')
if keyword and pagenum:
print('正在获取数据,请耐心等待。预计 %d 秒后开始下载' %(int(pagenum)*2+3))
getpageshtml(int(pagenum),keyword)
代码不长,getpageshtml函数负责使用Selenium框架获取到多页的图片搜索结果的HTML,然后downpics函数用正则解析出所有的图片URL并将图片文件写到本地。运行效果如下: