python爬虫从入门到放弃(一)——试用bs4, request爬百度股票
文章实践主要来自于:https://mp.weixin.qq.com/s/FiKqb06nz0K0AD9VUWJapw
爬虫流程:
明确目的(哪些数据),确认网页可爬,查看源网页是否有需要的数据。
bs4简介
Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式。
python
with方法--
with语句执行的解析:
with context_expr() as var:
doSomething()
- 当with语句执行时,便执行上下文表达式(context_expr)(一般为某个方法)来获得一个上下文管理器对象,上下文管理器的职责是提供一个上下文对象,用于在with语句块中处理细节:
- 一旦获得了上下文对象,就会调用它的__enter__()方法,将完成with语句块执行前的所有准备工作,如果with语句后面跟了as语句,则用__enter__()方法的返回值来赋值;
- 当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法,__exit__()方法有3个参数,如果with语句正常结束,三个参数全部都是 None;如果发生异常,三个参数的值分别等于调用sys.exc_info()函数返回的三个值:类型(异常类)、值(异常实例)和跟踪记录(traceback),相应的跟踪记录对象。
- 因为上下文管理器主要作用于共享资源,__enter__()和__exit__()方法基本是完成的是分配和释放资源的低层次工作,比如:数据库连接、锁分配、信号量加/减、状态管理、文件打开/关闭、异常处理等。
3、自定义类使用with来管理
完整代码示例:
1 # -*- coding: utf-8 -*- 2 3 4 # Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment . 5 6 import requests 7 from bs4 import BeautifulSoup 8 import traceback 9 import re 10 11 12 13 def getHTMLText(url): 14 try: 15 r = requests.get(url) 16 r.raise_for_status() 17 r.encoding = r.apparent_encoding 18 return r.text 19 except: 20 return "" 21 22 23 def getStockList(lst, stockURL): 24 html = getHTMLText(stockURL) 25 # 返回的是BeautifulSoup对象 26 soup = BeautifulSoup(html, 'html.parser') 27 a = soup.find_all('a') 28 for i in a: 29 try: 30 href = i.attrs['href'] 31 lst.append(re.findall(r"[s][hz]\d{6}", href)[0]) 32 except: 33 continue 34 35 def getStockInfo(lst, stockURL, fpath): 36 count = 0 37 for stock in lst: 38 url = stockURL + stock + ".html" 39 html_doc = getHTMLText(url) 40 try: 41 if html_doc == "": 42 continue 43 infoDict = {} 44 45 soup = BeautifulSoup(html_doc, 'html.parser') 46 # 寻找所有属性为stock-bets的div标签,构成一个list 47 stockInfo = soup.find('div', attrs={'class': 'stock-bets'}) 48 # 找到所有class==bets-name的标签 49 50 # 使用find方法返回的同样是bs4对象,find返回的是由bs4对象构成的list 51 name = stockInfo.find(attrs={'class': 'bets-name'}) 52 # .text方法以list对象的方式返回tag的内容 53 infoDict.update({'股票名称': name.text.split[0]}) 54 # 每个股票中每个key正好对应一个值,这里恰好不用数据处理 55 keyList = stockInfo.find_all('dt') 56 valueList = stockInfo.find_all('dd') 57 for i in range(len(keyList)): 58 key = keyList[i].text 59 val = valueList[i].text 60 infoDict[key] = val 61 # 内置open()函数,打开一个文件用于追加。 62 # 如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 63 # 使用with语句时,如文件打开发生异常,可记录跟踪调查 64 with open(fpath, 'a', encoding='utf-8') as f: 65 f.write(str(infoDict) + '\n') 66 count = count + 1 67 # 通过\r使得每次打印的时候光标换行到上一行开头,使得看起来进度条是连续的 68 print("\r当前进度: {:.2f}%".format(count * 100 / len(lst)), end="") 69 except: 70 count = count + 1 71 print("\r当前进度: {:.2f}%".format(count * 100 / len(lst)), end="") 72 continue 73 74 75 def main(): 76 stock_list_url = 'http://quote.eastmoney.com/stocklist.html' 77 stock_info_url = 'https://gupiao.baidu.com/stock/' 78 output_file = '/home/icarus/code/pachong_stock/BaiduStockInfo.txt' 79 slist = [] 80 getStockList(slist, stock_list_url) 81 getStockInfo(slist, stock_info_url, output_file) 82 main()