爬虫进阶

利用多线程爬取数据

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 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。我们有两种办法来处理这种情况:

  1. 直接分析ajax调用的接口。这样虽然代码量小,不过需要很深的js功底,要不然极容易被发现是爬虫。
  2. 使用seleniumchromedriver来模拟登陆。这样虽然繁琐,不过很稳定。Selenium相当于是一个机器人。可以模拟人类在浏览器上的一些行为,自动处理浏览器上的一些行为,比如点击,填充数据,删除cookie等。chromedriver是一个驱动Chrome浏览器的驱动程序,使用他才可以驱动浏览器。

selenium快速入门与基本操作

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:chromedriverchromedriver.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:chromedriverchromedriver.exe"
driver = webdriver.Chrome(executable_path=driver_path,options=options)
driver.get("http://www.ip138.com/")

图像验证码识别技术和tesseract

tesseract安装与配置

GIT官网

设置系统变量

在Windows下把tesseract.exe所在的路径添加到PATH环境变量中。还有一个环境变量需要设置的是,要把训练的数据文件路径也放到环境变量中。在环境变量中,添加一个TESSDATA_PREFIX=C:path_to_tesseractdata eseractdata。

在cmd中使用

tesseract 图片路径 文件路径

文件路径不需要添加后缀名也会默认为.txt

python代码中实现

import pytesseract
from PIL import Image
##获得tesseract可执行文件地址
pytesseract.pytesseract.tesseract_cmd = r"D:	esseract	esseract.exe"
##利用该模块打开图片文件
image = Image.open(r"C:UsersDELLDesktopa.png")
##image_to_string()方法转换成字符串
text = pytesseract.image_to_string(image)
print(text)
原文地址:https://www.cnblogs.com/MingleYuan/p/10742379.html