最近几天因业务需求,需进行数据抓取,但是使用node.js抓取时,发现目标网站必须使用viewstatue进行模拟请求,所以使用selenium进行模拟抓取,下面主要记录本次的难点。
1、selenium的配置及使用
在开始前必须进行环境配置,先下载selenium对应本机chrome浏览器的版本,可以参照https://www.cnblogs.com/JHblogs/p/7699951.html自行下载。
selenium元素选择可以参考https://www.cnblogs.com/yoyoketang/p/6123890.html,有版本区别。
selenium使用的主要代码:
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import Select
abspath = os.path.abspath(r"chromedriver.exe")
chrome_options = webdriver.ChromeOptions()
#是否使用无页面模式
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
dr = webdriver.Chrome(abspath,chrome_options=chrome_options)
先是Python的引用,下面地址设置,我直接和代码放在一起,也可以设置绝对地址。
使用无页面模式可以加快抓取效率,但是在测试时有页面可以更加直观。
2、验证码的识别
因为要模拟登录所以需要用到验证码识别,本次使用公司之前购买验证识别网站进行识别,但是在使用过程中,因为目标网站验证应该存储在用户session中,所以需要在请求时带着cookie进行请求。
import requests
from requests.cookies import RequestsCookieJar
cookies = dr.get_cookies()
cookie_jar = RequestsCookieJar()
for cookie in cookies:
cookie_jar.set(cookie['name'], cookie['value'], domain="目标网站host")
element = dr.find_element_by_id('imgs')
img_url = element.get_attribute('src')
data = requests.get(img_url,cookies=cookie_jar).content
f = open('11.png', 'wb')
f.write(data)
f.close()
#验证码识别
codelib = lib.httplib.httphelper()
info = codelib.validatecode(data)
code = dr.find_element_by_id('txtValidateCode')
code.send_keys(info['pic_str'])
先通过selenium打开目标网站登录页面,获取cookie,通过cookie进行模拟验证码请求,获取验证图片二进制文件,在进行图片识别,最终实现登录。
3、PyQuery的使用及数据存储
因为之前开发使用js较多,所以其它获取元素方法使用不习惯,所以使用PyQuery进行页面元素获取。期间遇到PyQuery无法获取页面元素问题,可以参考https://blog.csdn.net/jewely/article/details/83281228,则可以正常解析。
from pyquery import PyQuery as pq
list_all = []
bo = True
flag = 1
while(True):
print('正在抓取第%s页,已经抓取%s条!'%(flag,len(list_all)))
doc = pq(dr.page_source,parser="html")
#头部文件、实际文件
items_head = doc('.tableList thead tr')
items_body = doc('.tableList tbody tr')
row_hd =[]
if bo:
for ii in items_head.find('th'):
row_hd.append(pq(ii).text().strip())
for item in items_body:
row = []
for ii in pq(item).find('td'):
row.append(pq(ii).text().strip())
if bo:
list_all.append(row_hd)
bo = False
list_all.append(row)
#每到20页保存一次
if flag%20==0 :
saveexcel(list_all)
#判断下一页是否存在
boex = True
try:
dr.find_element_by_link_text('下一页')
except Exception as err:
boex = False
if boex:
flag = flag + 1
nextbtn = dr.find_element_by_link_text('下一页')
nextbtn.click()
else:
break
因为目标网站无法进行页面跳转,所以使用点击下一页的方式进行,直到无法进行点击为止,则说明抓取完成。如果可以跳转页数,则需要进行异常捕获,出现异常时重新进行请求。