实用Python程序设计MOOC-第十二章网络爬虫设计
[TOC]
实用Python程序设计MOOC-第十二章网络爬虫设计 爬虫基本原理 爬虫的用途和原理 1) 在网络上搜集数据(比如搜索引擎) 2) 模拟浏览器快速操作(抢票,抢课,抢挂号…..) 3) 模拟浏览器操作,替代填表等重复操作
最基本的爬虫写法 数据获取型爬虫的本质就是自动获取网页并抽取其中的内容 1) 手工找出合适的url(网址) 。 2) 用浏览器手工查看url对应的网页,并查看网页源码,找出包含想要的内容(文件名,链接等)的字符串的模式。 3) 程序中获取url对应的网页。 4) 程序中用正则表达式或BeautifulSoup库抽取网页中想要的内容并保存。
示例:获取百度图片的搜索结果图片
/在百度图片敲关键字“desk”进行搜索
搜索后看浏览器地址栏的地址:搜索后看浏览器地址栏的地址
猜测只要在浏览器输入下面地址的word=内容,替换其中的单词,就能搜到图片:
1 2 3 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=desk 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,并用浏览器查看源码(chrome)
在源码中查找
复制出来的图片地址:https://img1.baidu.com/it/u=716463119,473541077&fm=26&fmt=auto&gp=0.jpg
为某张图片的网络地址,此链接是百度保存的缩略图的网址
查看网页源代码后搜索图片连接,找到源码:716463119,473541077&fm=26&fmt=auto&gp=0.jpg
发现图片链接在网页里都是这样的:{"thumbURL":"https://img1.baidu.com/it/u=716463119,473541077&fm=26&fmt=auto&gp=0.sjpg", "adType":"0","midd
即thumbURL后跟的是图片连接。
可以用正则表达式提取图片链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import reimport requests def getHtml (url ): def getBaiduPictures (word,n ): 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\":.*?\"(.*?)\"' i = 0 for x in re.findall(pt, html): print (x) x = x.lower() try : r = requests.get(x, stream=True ) f = open ('{0}{1}.jpg' .format (word,i), "wb" ) f.write(r.content) f.close() i = i + 1 except Exception as e : pass if i >= n: break getBaiduPictures("猫" , 5 ) getBaiduPictures("熊猫" , 5 )
用requests库获取网页 用requests.get获取网页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def getHtml (url ): import requests 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: print (e) return ""
用requests.get获取网页(编码识别加强版) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 def getHtml (url ): import sys, requests import chardet 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) ecd = chardet.detect(r.content)['encoding' ] if ecd.lower() != sys.getdefaultencoding().lower(): r.encoding = ecd else : r.encoding = r.apparent_encoding return r.textv except Exception as e: print (e) return ""
用requests库获取网页的优势和局限
容易被反爬虫手段屏蔽
不能获取包含javascript生成的动态网页 用上面的getHtml函数,不能得到百度图片搜索结果网页,得到的网页是空网页(被反爬了)
弥补requests不足的其它获取网页的办法
使用selenium库 (慢,很容易被反爬,且已经被许多网站反爬,网上各种对付反爬的解决办法基本不管用,不推荐)
使用pyppeteer库(快,暂未被许多网站反爬,强烈推荐)
用selenium库获取网页 pip install selunium
需要chrome浏览器或firefox浏览器,此外还需要下载chrome驱动程序(chromedriver.exe)或firefox驱动程序(geckodriver.exe)
用selenium获取网页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def getHtml (url ): from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() options.add_argument('--headless' ) options.add_argument('--disable-gpu' ) driver = webdriver.Chrome( executable_path='c:/tmp/chromedriver.exe' , options=options) driver.get(url) html = driver.page_source driver.close() driver.quit() return html
用pyppeteer库获取网页
puppeteer是谷歌公司推出的可以控制Chrome浏览器的一套编程工具。一个日本工程师以此为基础推出了Python版本,叫pyppeteer。
pyppeteer的官网
启动一个浏览器Chromium,用浏览器装入网页。浏览器可以用无头模式(headless),即隐藏模式启动,也可以显式启动。
从浏览器可以获取网页源代码,若网页有javascript程序,获取到的是javascript被浏览器执行后的网页源代码。
可以向浏览器发送命令,模拟用户在浏览器上键盘输入、鼠标点击等操作,让浏览器转到其它网页。
selenium原理及功能和pyppeteer一样。
环境安装 pip install pyppeteer
要求Python版本 >= 3.6
必须下载并安装特殊版本的谷歌浏览器Chromium
可以将Chromium压缩包随便解压在哪个文件夹,然后在程序指明其中chrome.exe的位置。 也可以将Chromium解压到pyppeteer的安装文件夹下面。这个文件夹通常类似:C:\Users\username\AppData\Local\pyppeteer\pyppeteer\local-chromium\588429
把username要换成自己的windows用户名, 588429这里可能是别的数。 将Chromium压缩包里面的chrome-win32文件夹整个放在上面那个文件夹里面就行
预备知识:协程
协程就是前面加了’async’的函数(从Python 3.6开始有)
1 RuntimeWarning: coroutine 'XXXX' was never awaited
用pyppeteer获取网页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def getHtml (url ): import asyncio import pyppeteer as pyp async def asGetHtml (url ): browser = await pyp.launch(headless=False ) 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' ) await page.evaluateOnNewDocument( '() =>{ Object.defineProperties(navigator, \ { webdriver:{ get: () => false } }) }' ) await page.goto(url) text = await page.content() await browser.close() return text m = asyncio.ensure_future(asGetHtml(url)) asyncio.get_event_loop().run_until_complete(m) return m.result()
可以改进程序,只需要启动一次浏览器,生成一个page对象即可,以后获取不同网页都用相同page对象,所有事情完成后才关闭浏览器。
1 browser = await launch(headless=False , executablePath="c:/tmp/chrome-win32/chrome.exe" , userdataDir="c:/tmp" )
excutablePath
: 如果Chromium没有安装在默认文件夹下面,则需要指定其位置。userdataDir
: userdataDir指明用来存放浏览器工作期间存放临时文件的文件夹。不是必须,能够防止可能出现的莫名其妙的错误。
用BeautifulSoup库分析网页 分析并提取网页内容的三种方式
正则表达式(速度最快,但适应变化略差)
BeautifulSoup库 (速度是正则表达式的约几分之一)
selenium或pyppeteer的中的浏览器对象的查找元素函数(速度是正则表达式的约百分之一,用在需要模拟在网页中进行输入,点击按钮等操作的时候)
html文档(网页)中的tag tag格式通常为(少数没有正文和< /X >
):
1 2 3 <X attr1 ='xxx' attr2 ='yyy' attr3 ='zzz' …> nnnnnnnnnnnnnn </X >
X : tag的名字(name)
attr1,attr2… : tag的属性(attr) =后面跟着属性的值
nnnnnnnnnnnnnn : tag的正文(text)
例如:1 <a href ="www.sohu.com" id ='mylink' > 搜狐网</a >
a :tag的名字(name)
href, id : tag的属性(attr), =后面跟着属性的值
搜狐网 : tag的正文(text)
tag可以嵌套 1 2 3 4 5 6 7 <div id ="siteHeader" class ="wrapper" > <h1 class ="logo" > <div id ="topsearch" > <ul id ="userMenu" > <li > <a href ="http://openjudge.cn/" > 首页</a > </li > </div > </div >
用BeautifulSoup库分析html
1 pip install beautifulsoup4
1) 将html文档装入一个BeautifulSoup对象X 2) 用X对象的find
,find_all
等函数去找想要的tag对象 3) 对找到的tag对象,还可以用其find
,find_all
函数去,找它内部包含(嵌套)的tag对象 4) tag对象的text就是该对象里的正文(text), tag对象也可以看作是一个字典,里面包含各种属性(attr)及其值。
把html文档载入BeautifulSoup对象
1 2 3 4 5 6 7 8 9 10 11 12 13 str = ''' <div id="siteHeader" class="wrapper"> <h1 class="logo"> <div id="topsearch"> <ul id="userMenu"> <li ><a href="http://openjudge.cn/">首页</a></li> </div> </div> ''' 接地址 soup = bs4.BeautifulSoup(str , "html.parser" ) print (soup.find("li" ).text)
1 soup = bs4.BeautifulSoup(open ("c:\\tmp\\test.html" ,"r" ,encoding="utf-8" ), "html.parser" )
1 2 3 4 5 6 7 8 9 10 11 12 import requestsdef getHtml (url ): try : r = requests.get(url) r.raise_for_status() r.encoding = r.apparent_encoding return r.text except : return "" html = getHtml("https://cn.bing.com/dict/search?q=new" ) soup = bs4.BeautifulSoup(html,'html.parser' )
实例:用BeautifulSoup对象寻找想要的tag c:\tmp\test.html
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <!DOCTYPE HTML > <html > <body > <div id ="synoid" style ="display:block;" > <div class ="df_div2" > <div class ="de_title1" > adj.</div > <div class ="col_fl" > <a h ="ID=Dictionary,5237.1" href ="https://cn.bing.com/dict/search?q=novel" > <span class ="p1-4" > novel</span > </a > <p > <a h ="ID=Dictionary,5238.1" href ="https://cn.bing.com/dict/search?q=newfangled" > <span class ="p1-4" > newfangled</span > </a > </div > <a href ="http://www.baidu.com" id ="searchlink1" class ="sh1" > 百度</a > <a href ="http://www.google.com" id ="searchlink1" class ="sh2" > 谷歌</a > </div > </div > </body > </html >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import bs4soup = bs4.BeautifulSoup(open ("c:\\tmp\\test.html" , encoding = "utf-8" ),"html.parser" ) diva = soup.find("div" ,attrs={"id" :"synoid" }) if diva != None : for x in diva.find_all("span" ,attrs={"class" :"p1-4" }): print (x.text) for x in diva.find_all("a" ,attrs={"id" :"searchlink1" }): print (x.text) x = diva.find("a" ,attrs={"id" :"searchlink1" ,"class" :"sh2" }) if x != None : print (x.text) print (x["href" ]) print (x["id" ])
输出:
1 2 3 4 5 6 7 novel newfangled 百度 谷歌 谷歌 http://www.google.com searchlink1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import bs4soup = bs4.BeautifulSoup(open ("c:\\tmp\\test.html" ,encoding="utf-8" ),"html.parser" ) for x in soup.find_all("span" ,attrs={"class" :"p1-4" }): print (x.text) for x in soup.find_all("a" ,attrs={"id" :"searchlink1" }): print (x.text) x = soup.find("a" ,attrs={"id" :"searchlink1" ,"class" :"sh2" }) if x != None : print (x.text) print (x["href" ]) print (x["id" ])
实例:爬取每日股票交易信息 创业板股票交易代码大全 深圳股票交易代码大全 上证股票交易代码大全
查看源代码:
1 2 3 4 5 <li > <a href ="/gupiao/600151/" > 航天机电(600151)</a > </li > <li > <a href ="/gupiao/600156/" > 华升股份(600156)</a > </li > <li > <a href ="/gupiao/600160/" > 巨化股份(600160)</a > </li > <li > <a href ="/gupiao/600161/" > 天坛生物(600161)</a > </li > <li > <a href ="/gupiao/600162/" > 香江控股(600162)</a > </li >
东方财富网每日股票交易信息单只股票:
quote.eastmoney.com/sh600000.html 上证 quote.eastmoney.com/sz000017.html 深圳或创业板
该页面查看源代码,看不到 12.17, 12.51等交易数据。说明源代码里面包含javascript程序, 浏览器执行javascript程序以后,才能得到显示的页面。
因此python程序需要在取到网页后,还要执行里面的javascript程序,才能得到股票数据
用requests.get无法得到显示的网页。必须用selenium或者pyppeteer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import reimport asyncio import pyppeteer as pypimport bs4async def antiAntiCrawler (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 getStockCodes (page ): codes = [] html = await page.content() pt = '<a href="/gupiao/[^"]*">([^<]*\(\d+\))</a>' for x in re.findall(pt, html): codes.append(x) return codes async def getStockInfo (url ): browser = await pyp.launch(headless=False ) page = await browser.newPage() await antiAntiCrawler(page) await page.goto(url) codes = await getStockCodes(page) for x in codes[:3 ]: print ("-----" , x) pos1, pos2 = x.index("(" ), x.index(")" ) code = x[pos1 + 1 :pos2] url = "https://quote.eastmoney.com/sh" + code + ".html" await page.goto(url) html = await page.content() pt = '<td>([^<]*)</td>.*?<td[^>]*id="gt\d*?"[^>]*>([^<]*)</td>' for x in re.findall(pt, html, re.DOTALL): print (x[0 ], x[1 ]) await browser.close() url = "https://www.banban.cn/gupiao/list_sh.html" loop = asyncio.get_event_loop() loop.run_until_complete(getStockInfo(url))
1 2 html = await page.content() print (html)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <tr > <td > 今开: </td > <td id ="gt1" class ="txtl" data-bind ="46" > 1.22</td > <td > 最高: </td > <td id ="gt2" class ="txtl" data-bind ="44" > 1.22</td > <td > 涨停: </td > <td id ="gt3" class ="txtl red" data-bind ="51" > 1.34</td > <td > 换手: </td > <td id ="gt4" class ="txtl" data-bind ="tr" > 1%</td > <td > 成交量: </td > <td id ="gt5" class ="txtl" data-bind ="47" > 316.4万手</td > ..................... <td id ="gt6" class ="txtl" data-bind ="pe" > 245.41</td > <td > 总市值: </td > <td id ="gt7" class ="txtl" data-bind ="tmv" > 547.0亿</td > </tr >
正则表达式pt对应:1 2 <td > 今开: </td > <td id ="gt1" class ="txtl" data-bind ="46" > 1.22</td >
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ----- 包钢股份(600010) 今开: 1.22 最高: 1.22 涨停: 1.34 换手: 1% 成交量: 316.4万手 总市值: 547.0亿 昨收: 1.22 最低: 1.19 跌停: 1.1 量比: 1.04 成交额: 3.81亿 市净: 1.03 流通市值: 380.1亿 ----- 四川路桥(600039) 今开: 4.94 最高: 4.95 涨停: 5.43 换手: 0.49% 成交量: 17.64万手 总市值: 232.8亿 昨收: 4.94 最低: 4.86
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 async def getStockCodes (page ): codes = [] html = await page.content() soup = bs4.BeautifulSoup(html, "html.parser" ) for x in soup.find_all("li" ): a = x.find("a" ) if ( "(" in a.text and ")" in a.text): codes.append(a.text) return codes async def getStockCodes (page ): codes = [] elements = await page.querySelectorAll("li" ) for e in elements: a = await e.querySelector("a" ) obj = await a.getProperty("text" ) text = await obj.jsonValue() if ( "(" in text and ")" in text): codes.append(text) return codes
弹出菜单点“检查”,可以看到附近元素对应的源代码(查看源代码看不到)
需要登录的爬虫
爬取Openjudge自己提交通过的所有程序源码
程序命令浏览器模拟登录过程,即输入用户名密码、点登录按钮
或:程序启动浏览器,等待手工登录后,程序再继续爬虫操作(对有验证码的情况,或者懒得写代码的情况)
更高级做法:不用浏览器,经数据包分析后,用requests库进行数据传输进行登录
鼠标右键点击右上角的“个人首页”,在弹出的菜单上选“检查” :
点击 “个人首页”, 进入:
1 <a href ="http://cxsjsxmooc.openjudge.cn/2020t1fallall2/solution/25212869/" class ="result-right" > Accepted</a >
点击某个题的“Accepted”链接,进入:
1 2 3 4 5 6 7 8 9 <pre class ="sh_python" > n = int(input()) lst = [] for i in range(n): s = input().split() lst.append((s[0], int(s[1]))) lst.sort(key= lambda x : (-x[1], x[0])) for x in lst: print(x[0], x[1])</pre >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import asyncioimport pyppeteer as pypasync def antiAntiCrawler (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 , userdataDir="c:/tmp" , 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 ("XXXXX@qq.com" ) element = await page.querySelector("#password" ) await element.type ("XXXXXXXXX" ) 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" ) page2 = await browser.newPage() await antiAntiCrawler(page2) for element in elements[:2 ]: obj = await element.getProperty("href" ) url = await obj.jsonValue() await page2.goto(url) element = await page2.querySelector("pre" ) obj = await element.getProperty("innerText" ) text = await obj.jsonValue() print (text) print ("-------------------------" ) await browser.close() def main (): url = "http://openjudge.cn/auth/login/" syncio.get_event_loop().run_until_complete(getOjSourceCode(url)) main()
pyppeteer+requests编写快速爬虫
requests要对付登录比较麻烦(要用到抓包等技巧)
pyppeteer没有requests快(因为要浏览器渲染网页)
对于需要登录,且登录后的网页都不是javascript生成的动态网页的情况,可以使用pyppeteer登录后,再用requests做剩下的事情。
网址: http://openjudge.cn/user/2312/
不登录,访问同样网址,提示没有登录 同样的访问请求,服务器怎么知道浏览器是否登录过?
预备知识: cookie和session
登录成功后,服务器向浏览器发送一些身份标识数据,称为cookie,浏览器以后每次向服务器发送请求,都带上cookie,服务器就能知道请求来自前面那个登录的浏览器了。
服务器在内存为浏览器维护一个session,每个浏览器对应不同的session,里面存放着该浏览器的状态(比如一系列的填表等步骤已经进行到什么程度),不同的session有不同的session id,浏览器发送请求的时候,如果带上session id,服务器也能知道是哪个浏览器在请求。
在客户计算机上由cookie可以生成标识同一个浏览器的session。
工作原理
pyppeteer的浏览器的页面有cookies()函数可以获得cookie
requests.Session()可以生成一个空session
session的cookies.update(cookies)函数可以根据cookies生成相应session
session的get(url)函数,可以向服务器发送带session的请求
获得cookie,生成相应session以后,爬取网页都用session的get函数进行(前提:网页不是javascript生成的。如果是,依然用pyppeteer的浏览器爬取)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 import asyncioimport pyppeteer as pypimport bs4import requestsdef sessionGetHtml (session, 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' } try : result = session.get(url, headers=fakeHeaders) result.encoding = result.apparent_encoding return result.text except Exception as e: print (e) return "" async def makeSession (page ): cookies = await page.cookies() cookies1 = {} for cookie in cookies: cookies1[cookie['name' ]] = cookie['value' ] session = requests.Session() session.cookies.update(cookies1) return session async def antiAntiCrawler (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 , userdataDir = "c:/tmp" , args=[f'--window-size={width} ,{height} ' ]) page = await browser.newPage() await antiAntiCrawler(page) await page.setViewport({'width' : width, 'height' : height}) await page.goto(loginUrl) 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" ) session = await makeSession(page) for element in elements[:2 ]: obj = await element.getProperty("href" ) url = await obj.jsonValue() html = sessionGetHtml(session, url) soup = bs4.BeautifulSoup(html, "html.parser" ) element = soup.find("pre" ) print (element.text) print ("-------------------------" ) await browser.close() def main (): url = "http://openjudge.cn/auth/login/" asyncio.get_event_loop().run_until_complete(getOjSourceCode(url)) main()
补充tips 绝对网址和相对网址
1 2 3 4 5 6 r = requests.get("http://openjudge.cn" ) print (r.url) session = requests.session() r = session.get("http://openjudge.cn" ) print (r.url)
1 2 3 4 browser = await pyp.launch(headless=False ) page = await browser.newPage() await page.goto("http://openjudge.cn" )print (page.url)
反反爬
连续的两个操作之间,加入适当延时,模拟人的动作,以免因动作太快被识破
1 2 import timetime.sleep(2 )
也可以用time.sleep(...)
来等待一段时间,确保网页加载完成