郭炜老师mooc第十二章网络爬虫设计

网络爬虫

示例:获取百度图片的搜索结果图片(用requests.get获取网页)

# 示例:获取百度图片的搜索结果图片

import re
import requests #request库用于获取网络资源 pip install requests

# 用requests.get获取网页
def getHtml(url): #获取网址url的网页
    fakeHeaders = {'User-Agent': #用于伪装浏览器发送请求
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
    AppleWebKit/537.36 (KHTML, like Gecko) \ '
    'Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77',
    'Accept': 'text/html,application/xhtml+xml,*/*'}
    try:
        r = requests.get(url,headers = fakeHeaders)
        r.encoding = r.apparent_encoding #确保网页编码正确
        return r.text #返回值是个字符串,内含整个网页内容
    except Exception as e:  #防止错误url
        print(e)
        return "" 
#用法:html = getHtml("http://openjudge.cn")

def getBaiduPictures(word, n):
#下载n个百度图片搜来的关于word的图片保存到本地
    url ="""https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1
    &fm=index&fr=&hs=0&xthttps=111111&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=
    &face=0&istype=2&ie=utf-8&word="""

    url += word
    html = getHtml(url)
    pt = '\"thumbURL\":\"(.*?)\"' # 这个正则表达式也可以
    
#     pt = '\"thumbURL\":.*?\"(.*?)\"' #正则表达式,用于寻找图片网址
    i = 0
    #"thumbURL":"https://img1.baidu.com/it/u=716463119,473541077&fm=26&fmt=auto&gp=0.jpg",

    for x in re.findall(pt, html): #x就是图片url
        print(x)  
        x = x.lower()
        try:
            r = requests.get(x, stream=True)#获取x对应的网络资源
            f = open(r"D:\桌面\爬虫项目\{0}{1}.jpg".format(word,i), "wb")
            #"wb"表示二进制写方式打开文件
            f.write(r.content) #图片内容写入文件
            f.close()
            i = i + 1
        except Exception as e :
            pass
        if i >= n:
            break
    
getBaiduPictures("猫", 5)
getBaiduPictures("熊猫" , 5)

requests库获取网页的优势和局限:

pyppeteer的介绍

用pyppeteer获取网页

# 示例:获取百度图片的搜索结果图片

import re
import requests #request库用于获取网络资源 pip install requests

import asyncio

import nest_asyncio
nest_asyncio.apply()
# 这两句代码是出现 RuntimeError: This event loop is already running 问题的解决方案

# 用pyppeteer获取网页
def getHtml(url): #暂时适用于百度图片搜索
    import pyppeteer as pyp
    async def asGetHtml(url): #获取url对应网页的源代码 
        browser = await pyp.launch(headless=False, executablePath = r"E:\Download_Softwear\chromium\chrome-win\chrome-win\chrome.exe")
        # 启动Chromium,browser即为Chromium浏览器,非隐藏启动
        '''
        launch的其它参数
        browser = await launch(headless=False,executablePath = "c:/tmp/chrome-win32/chrome.exe",
        userdataDir = "c:/tmp")
        excutablePath: 如果Chromium没有安装在默认文件夹下面,则需要指定其位置
        userdataDir: userdataDir指明用来存放浏览器工作期间存放临时文件的文件夹,
        不是必须,能够防止可能出现的莫名其妙的错误
        
        launch的英文释义是发射,这里是 指的启动个浏览器,这个函数是个异步函数,
        所以必须await ,不然是会报错的
        '''
        
        page = await browser.newPage()# 在浏览器中打开一个新页面(标签), 启动一个新的 选项卡页面
        await page.setUserAgent('Mozilla/5.0 (Windows NT 6.1; \
        Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \
        Chrome/78.0.3904.70 Safari/537.36') #反反爬措施
        '''
        修改终端:
        Puppeteer 提供了几个有用的方法让我们可以修改设备信息
        page.setViewport(viewport)
        page.setUserAgent(userAgent)
        '''
        
        await page.evaluateOnNewDocument(
        '() =>{ Object.defineProperties(navigator, \{ webdriver:{ get: () => false } }) }' ) #反反爬措施
        
        await page.goto(url) # 装入url对应的网页;前往一个页面
        text = await page.content() # page.coutent就是网页源代码字符串
        await browser.close() # 关闭浏览器
        return text
    #速度大约比用requests.get慢5,6倍
    
    m = asyncio.ensure_future(asGetHtml(url)) #协程外启动协程
    asyncio.get_event_loop().run_until_complete(m) #等待协程结束
    '''
    run_until_complete是一个阻塞调用,知道协程运行结束才返回;
    它的参数是一个future,但是我们传给它的却是协程对象,它在内部做了检查,通过ensure_future函数
    把协程对象包装成了future
    '''
    return m.result() #返回的就是asGetHtml的返回值 text


# 用requests.get获取网页
# def getHtml(url): #获取网址url的网页
#     fakeHeaders = {'User-Agent': #用于伪装浏览器发送请求
#     'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
#     AppleWebKit/537.36 (KHTML, like Gecko) \ '
#     'Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77',
#     'Accept': 'text/html,application/xhtml+xml,*/*'}
#     try:
#         r = requests.get(url,headers = fakeHeaders)
#         r.encoding = r.apparent_encoding #确保网页编码正确
#         return r.text #返回值是个字符串,内含整个网页内容
#     except Exception as e:  #防止错误url
#         print(e)
#         return "" 
#用法:html = getHtml("http://openjudge.cn")

def getBaiduPictures(word, n):
#下载n个百度图片搜来的关于word的图片保存到本地
    url ="""https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1
    &fm=index&fr=&hs=0&xthttps=111111&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=
    &face=0&istype=2&ie=utf-8&word="""

    url += word
    html = getHtml(url)
    pt = '\"thumbURL\":\"(.*?)\"' # 这个正则表达式也可以
    
#     pt = '\"thumbURL\":.*?\"(.*?)\"' #正则表达式,用于寻找图片网址
    i = 0
    #"thumbURL":"https://img1.baidu.com/it/u=716463119,473541077&fm=26&fmt=auto&gp=0.jpg",

    for x in re.findall(pt, html): #x就是图片url
        print(x)  
        x = x.lower()
        try:
            r = requests.get(x, stream=True)#获取x对应的网络资源
            f = open(r"D:\桌面\爬虫项目\{0}{1}.jpg".format(word,i), "wb")
            #"wb"表示二进制写方式打开文件
            f.write(r.content) #图片内容写入文件
            f.close()
            i = i + 1
        except Exception as e :
            pass
        if i >= n:
            break


getBaiduPictures("猫", 10)
getBaiduPictures("熊猫" , 15)

出现 RuntimeError: This event loop is already running 问题解决:
查阅博客后,发现所使用的 Python 编辑器为 Spyder,其连接着 IPython 内核,而 IPython 内核本身在事件循环上运行,而 asyncio 不允许嵌套其事件​​循环,因此会出现如上图的错误信息。
输入这两句代码即可:

import nest_asyncio
nest_asyncio.apply()

pyppeteer最为核心类Page的接口方法

Page类选择器相关方法有5个,并且这五个都有别名,分别是:

J()别名querySelector()

JJ()别名querySelectorAll()

JJeval()别名querySelectorAllEval()

Jeval()别名querySelectorEval()

Jx()别名xpath()

协程函数 querySelector(selector:str)

获取匹配的元素的selector

参数:搜索元素的选择器字符串。

返回[ElementHandle]或者None。

协程函数 querySelectorAll(selector:str)

获取匹配的所有元素selector作为列表。

参数:搜索元素的选择器

返回列表或返回空列表。

协程函数 querySelectorAllEval(selector:str,pageFunction:str,*args)

对所有匹配元素执行js

参数:

selector(str)-选择器。

pageFunction(str)-要在浏览器上运行的JavaScript函数的字符串,此函数将匹配元素的数组作为第一个参数。

args(Any)-传递给pageFunction的其他参数。

协程函数 querySelectorEval(selector:str,pageFunction:str,*args)

对匹配的元素执行js函数

参数:

selector(str)-定位的选择器字符串。

pageFunction(str)-要在浏览器上计算的JavaScript函数的字符串,此函数采用与选择器匹配的元素作为第一个参数。

args(Any)-传递给pageFunction的参数。

如果没有元素匹配,则此方法会引发错误selector

click()

click() 方法模拟鼠标单击元素。

此方法可用于执行对元素的单击,就像用户手动单击它一样。

pyppeteer的学习链接:

https://www.cnblogs.com/eliwang/p/14948012.html

爬取Openjudge自己提交通过的所有程序源码

# 爬取Openjudge自己提交通过的所有程序源码

import asyncio
import pyppeteer as pyp
import time

import nest_asyncio
nest_asyncio.apply()

async def antiAntiCrawler(page):
#为page添加反反爬虫手段
    await page.setUserAgent('Mozilla/5.0 (Windows NT 6.1; Win64; x64) \ '
    'AppleWebKit/537.36 (KHTML, like Gecko) '
    'Chrome/78.0.3904.70 Safari/537.36')
    await page.evaluateOnNewDocument(
    '() =>{ Object.defineProperties(navigator,'
    '{ webdriver:{ get: () => false } }) }')

    
async def getOjSourceCode(loginUrl):
    width, height = 1400, 800 #网页宽高
    browser = await pyp.launch(headless=False, executablePath = r"E:\Download_Softwear\chromium\chrome-win\chrome-win\chrome.exe",
    args=[f'--window-size={width},{height}'])
    
    page = await browser.newPage()
    await antiAntiCrawler(page) #为page页面提供反爬虫手段
    await page.setViewport({'width': width, 'height': height})
    await page.goto(loginUrl)
    #若手动登录,则以下若干行可以去掉
    '''
    如果没有定义class或者有多个相同的class时可以通过id获取,区别在于class传参是 "." 加class名称  
    而id传参是  "#" 加id名称
    '''
    element = await page.querySelector("#email") #找到账户输入框
    await element.type("你的账号") # 输入邮箱
    element = await page.querySelector("#password") #找到密码输入框
    await element.type("你的密码") # 输入密码
#     type(): 往输入框中输入内容,第一个参数为 CSS 选择器,第二个为文本内容

    element = await page.querySelector("#main > form > div.user-login >p:nth-child(2) > button") #找到登录按钮
     
    await element.click() # 点击登录按钮
#     click() 方法模拟鼠标单击元素。此方法可用于执行对元素的单击,就像用户手动单击它一样。

    #若手动登录,则以上若干行可以去掉

    await page.waitForSelector("#main>h2",timeout=30000) #等待"正在进行的比赛...."标题出现
    element = await page.querySelector("#userMenu>li:nth-child(2)>a")
    #找"个人首页"链接
    await element.click() #点击个人首页链接
    await page.waitForNavigation() #等新网页装入完毕
    elements = await page.querySelectorAll(".result-right")
    # class传参是 "." 加class名称
    #找所有"Accepted"链接, 其有属性 class="result-right"
    
    page2 = await browser.newPage() #新开一个页面 (标签)
    await antiAntiCrawler(page2)

    for element in elements[:2]: #只打印前两个程序
        obj = await element.getProperty("href") #获取href属性
        url = await obj.jsonValue()
        await page2.goto(url) #在新页面(标签)中装入新网页
        element = await page2.querySelector("pre") #查找pre tag
        obj = await element.getProperty("innerText") #取源代码
        text = await obj.jsonValue()
        print(text)
        print("-------------------------")
        
    time.sleep(10)
    
    await browser.close()
                                       
def main():
    url = "http://openjudge.cn/auth/login/"
    asyncio.get_event_loop().run_until_complete(getOjSourceCode(url))
main()

pyppeteer+requests编写快速爬虫

爬取Openjudge自己提交通过的所有程序源码(pyppeteer+requests编写快速爬虫)

# 爬取Openjudge自己提交通过的所有程序源码(pyppeteer+requests编写快速爬虫)

import asyncio
import pyppeteer as pyp
import time
import bs4
import requests

import nest_asyncio
nest_asyncio.apply()

def sessionGetHtml(session,url): #发送带session的网页请求
    fakeHeaders = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
    AppleWebKit/537.36 (KHTML, like Gecko) \
    Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77'
    } # 伪装浏览器用的请求头
    try:
        result = session.get(url,headers = fakeHeaders)
#         session的get(url)函数,可以向服务器发送带session的请求
#         获得cookie,生成相应session以后,爬取网页都用session的get函数进行

        result.encoding = result.apparent_encoding
        return result.text
    except Exception as e:
        print(e)
        return ""

async def makeSession(page):
# 返回一个session,将其内部cookies修改成pypeteer浏览器页面对象中的cookies
    cookies = await page.cookies() #cookies是一个列表,每个元素都是一个字典
#     pyppeteer的浏览器的页面有cookies()函数可以获得cookie

    cookies1 = {}
    for cookie in cookies: # requests中的cookies只要 "name"属性
        cookies1[cookie['name']] = cookie['value']
    session = requests.Session()
#     requests.Session()可以生成一个空session

    session.cookies.update(cookies1)
#     session的cookies.update(cookies)函数可以根据cookies生成相应session

    return session
# 获得cookie,生成相应session以后,爬取网页都用session的get函数进行

    '''
    pyppeteer的浏览器的页面有cookies()函数可以获得cookie
    requests.Session()可以生成一个空session
    session的cookies.update(cookies)函数可以根据cookies生成相应session
    session的get(url)函数,可以向服务器发送带session的请求
    获得cookie,生成相应session以后,爬取网页都用session的get函数进行
    (前提:网页不是javascript生成的。如果是,依然用pyppeteer的浏览器爬取
    '''

async def antiAntiCrawler(page):
#为page添加反反爬虫手段
    await page.setUserAgent('Mozilla/5.0 (Windows NT 6.1; Win64; x64) \ '
    'AppleWebKit/537.36 (KHTML, like Gecko) '
    'Chrome/78.0.3904.70 Safari/537.36')
    await page.evaluateOnNewDocument(
    '() =>{ Object.defineProperties(navigator,'
    '{ webdriver:{ get: () => false } }) }')

    
async def getOjSourceCode(loginUrl):
    width, height = 1400, 800 #网页宽高
    browser = await pyp.launch(headless=False, executablePath = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe",
    args=[f'--window-size={width},{height}'])
    
    page = await browser.newPage()
    await antiAntiCrawler(page)
    await page.setViewport({'width': width, 'height': height})
    await page.goto(loginUrl)
    #若手动登录,则以下若干行可以去掉
    element = await page.querySelector("#email") #找到账户输入框
    await element.type("你的邮箱") # 输入邮箱
    element = await page.querySelector("#password") #找到密码输入框
    await element.type("你的密码") # 输入密码
    
    element = await page.querySelector("#main > form > div.user-login >p:nth-child(2) > button") #找到登录按钮
     
    await element.click() # 点击登录按钮
    #若手动登录,则以上若干行可以去掉

    await page.waitForSelector("#main>h2",timeout=30000) #等待"正在进行的比赛...."标题出现
    element = await page.querySelector("#userMenu>li:nth-child(2)>a")
    #找"个人首页"链接
    await element.click() #点击个人首页链接
    await page.waitForNavigation() #等新网页装入完毕
    elements = await page.querySelectorAll(".result-right")
    #找所有"Accepted"链接, 其有属性 class="result-right"
    
    session = await makeSession(page)
    for element in elements[:1]:
        print("element\n", element)
        obj = await element.getProperty("href")
        url = await obj.jsonValue()
        html = sessionGetHtml(session, url)
        soup = bs4.BeautifulSoup(html, "html.parser")
        element = soup.find("pre")
        print(type(element))
        if(element != None):
            print(element.text)
        print("-------------------------")
    await browser.close()

    '''
    page2 = await browser.newPage() #新开一个页面 (标签)
    await antiAntiCrawler(page2)

    for element in elements[:2]: #只打印前两个程序
        obj = await element.getProperty("href") #获取href属性
        url = await obj.jsonValue()
        await page2.goto(url) #在新页面(标签)中装入新网页
        element = await page2.querySelector("pre") #查找pre tag
        obj = await element.getProperty("innerText") #取源代码
        text = await obj.jsonValue()
        print(text)
        print("-------------------------")
        
    time.sleep(10)
    
    await browser.close()
    '''

def main():
    url = "http://openjudge.cn/auth/login/"
    asyncio.get_event_loop().run_until_complete(getOjSourceCode(url))
main()

爬取豆瓣电影top250的电影名称:

爬取豆瓣电影top250的电影名称(完整代码与解释)-CSDN博客

相关推荐
Flying_Fish_roe15 分钟前
Spring Boot-RESTful API相关问题
spring boot·python·restful
叫我:松哥1 小时前
基于机器学习的癌症数据分析与预测系统实现,有三种算法,bootstrap前端+flask
前端·python·随机森林·机器学习·数据分析·flask·bootstrap
KookeeyLena81 小时前
如何限制任何爬虫爬取网站的图片
开发语言·c++·爬虫
我是瓦力1 小时前
球形包围框-Bounding Sphere-原理-代码实现
人工智能·python·深度学习·计算机视觉·3d
B站计算机毕业设计超人1 小时前
计算机毕业设计hadoop+spark知网文献论文推荐系统 知识图谱 知网爬虫 知网数据分析 知网大数据 知网可视化 预测系统 大数据毕业设计 机器学习
大数据·hadoop·爬虫·机器学习·spark·知识图谱·推荐算法
拉玛干1 小时前
社团周报系统可行性研究-web后端框架对比-springboot,django,gin
数据库·python·spring·golang
Yan-英杰2 小时前
Encountered error while trying to install package.> lxml
开发语言·python·pandas·pip·issue
RS&2 小时前
python学习笔记
笔记·python·学习
AI原吾2 小时前
解锁自动化新境界:KeymouseGo,让键盘和鼠标动起来!
运维·python·自动化·计算机外设·keymousego
卡卡_R-Python2 小时前
海洋气象编程工具-Python
开发语言·python