爬虫进阶
目录
利用多线程爬取数据
import threading
import requests
from lxml import etree
from urllib import request
import os
import re
from queue import Queue
class HtmlSprider(threading.Thread):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}
def __init__(self,page_queue,img_queue,*args,**kwargs):
super(HtmlSprider, self).__init__(*args,**kwargs)
self.page_queue = page_queue
self.img_queue = img_queue
def run(self):
while True:
if self.page_queue.empty():
break
url = self.page_queue.get()
self.parse_page(url)
def parse_page(self,url):
response = requests.get(url,headers=self.headers)
text = response.text
html = etree.HTML(text)
imgs = html.xpath("//div[@class='page-content text-center']//a//img")
for img in imgs:
if img.get('class') == 'gif':
continue
img_url = img.xpath(".//@data-original")[0]
suffix = os.path.splitext(img_url)[1]
suffix = re.sub(r"!dta", "", suffix)
alt = img.xpath(".//@alt")[0]
alt = re.sub(r'[,。??,/\\·]','',alt)
img_name = alt + suffix
self.img_queue.put((img_url,img_name))
class DownloadPicture(threading.Thread):
def __init__(self,page_queue,img_queue,*args,**kwargs):
super(DownloadPicture, self).__init__(*args,**kwargs)
self.page_queue = page_queue
self.img_queue = img_queue
def run(self):
while True:
if self.img_queue.empty():
if self.page_queue.empty():
return
img = self.img_queue.get(block=True)
url,filename = img
request.urlretrieve(url,'images/'+filename)
print(filename+' 下载完成!')
def main():
page_queue = Queue(100)
img_queue = Queue(500)
for x in range(1,10):
url = "http://www.doutula.com/photo/list/?page=%d" % x
page_queue.put(url)
for x in range(5):
t = HtmlSprider(page_queue,img_queue)
t.start()
for x in range(5):
t = DownloadPicture(page_queue,img_queue)
t.start()
if __name__ == '__main__':
main()
爬取动态数据
AJAX(Asynchronouse JavaScript And XML)
,翻译为异步JavaScript和XML。是在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。我们有两种办法来处理这种情况:
- 直接分析ajax调用的接口。这样虽然代码量小,不过需要很深的js功底,要不然极容易被发现是爬虫。
- 使用
selenium
和chromedriver
来模拟登陆。这样虽然繁琐,不过很稳定。Selenium
相当于是一个机器人。可以模拟人类在浏览器上的一些行为,自动处理浏览器上的一些行为,比如点击,填充数据,删除cookie
等。chromedriver是一个驱动Chrome浏览器的驱动程序,使用他才可以驱动浏览器。
selenium
快速入门与基本操作
from selenium import webdriver
import time
driver_path = "D:\\chromedriver\\chromedriver.exe" ##获取chromedriver可执行文件的地址
inputTag = webdriver.Chrome(executable_path=driver_path) ##传入chromedriver地址
inputTag.get("http://www.baidu.com") ##访问页面
inputTag = inputTag.find_element_by_id("kw")
inputTag.send_keys("python")
time.sleep(4)
关闭页面
driver.close()
:关闭当前页面driver.quit()
:退出浏览器
定位元素
find_element_by_id
:根据id来查找元素find_element_by_class_name
:根据类名查找元素find_element_by_name
:根据name属性的值来查找元素find_element_by_tag_name
:根据标签名来查找元素find_element_by_xpath
:根据xpath语法来获取元素find_element_by_css_selector
:根据css选择器选择元素
注意:把以上方法中的element
改为elements
就可以获取所有相关元素了
操作表单元素
- 操作输入框
#1.先获取需要填写内容的表单
#2.用send_keys方法发送要输入的值
inputTag = driver.find_element_by_id("kw")
inputTag.send_keys("python")
- 清除输入框里面的内容
inputTag.clear()
- 操作点击
rememberTag = driver.find_element_by_name("rememberMe")
rememberTag.click()
- 选择select标签
- 鼠标相关其他操作
click_and_hold(element)
:点击但不松开鼠标context_click(element)
:右键点击double_click(element)
:双击
行为链
inputTag = driver.find_element_by_id('kw')
submitTag = driver.find_element_by_id('su')
## 我们可以使用鼠标行为链类ActionChains来完成
actions = ActionChains(driver)
actions.move_to_element(inputTag)
actions.send_keys_to_element(inputTag,'python')
actions.move_to_element(submitTag)
actions.click(submitTag)
actions.perform()
Cookie
操作
- 获取所有Cookie:
for cookie in driver.get_cookies():
print(cookie
- 根据cookie的key获取value:
value = driver.get_cookie(key)
- 删除所有Cookie:
driver.delete_all_cookies()
- 删除某个cookie:
driver.delete_cookie(key)
页面等待
现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。因此,selenium提供了以下两种解决办法:
隐式等待
driver = webdriver.Chrome(executable_path=driver_path)
driver.implicitly_wait(10)
# 请求网页
driver.get("https://www.baidu.com/")
显示等待
显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
一些其他的等待条件:
presence_of_element_located
:某个元素已经加载完毕presence_of_all_element_located
:网页中所有满足条件的元素都加载完毕了element_to_be_cliable
:某个元素可以点击了
切换页面
from selenium import webdriver
driver_path = r"D:\chromedriver\chromedriver.exe"
driver = webdriver.Chrome(executable_path=driver_path)
driver.get("https://baidu.com/")
##打开新的一个页面
driver.execute_script("window.open('http://www.douban.com/')")
##切换到这个新的页面中
driver.driver.switch_to.window(driver.window_handles[1])
设置IP代理
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://110.52.235.241:9999")
driver_path = r"D:\chromedriver\chromedriver.exe"
driver = webdriver.Chrome(executable_path=driver_path,options=options)
driver.get("http://www.ip138.com/")
图像验证码识别技术和tesseract
tesseract
安装与配置
设置系统变量
在Windows下把tesseract.exe所在的路径添加到PATH环境变量中。还有一个环境变量需要设置的是,要把训练的数据文件路径也放到环境变量中。在环境变量中,添加一个TESSDATA_PREFIX=C:\path_to_tesseractdata\teseractdata。
在cmd中使用
tesseract 图片路径 文件路径
文件路径不需要添加后缀名也会默认为.txt
python代码中实现
import pytesseract
from PIL import Image
##获得tesseract可执行文件地址
pytesseract.pytesseract.tesseract_cmd = r"D:\tesseract\tesseract.exe"
##利用该模块打开图片文件
image = Image.open(r"C:\Users\DELL\Desktop\a.png")
##image_to_string()方法转换成字符串
text = pytesseract.image_to_string(image)
print(text)