当前位置:首页 > 科技 > 正文

Python爬虫实战:东方财富网股吧数据爬取(一)

Python爬虫实战系列文章目录




目录


前言

朋友托我写个爬虫,本身是个爬虫小白的我还是接受了此次重任,总共历时五天左右,过程中遇到过无数bug,好在一路披荆斩棘,还是大差不差的完成了此次委托!但感觉这次的经历还是有必要和大家分享一下,正好最近也没有写博文了,趁这次机会赶赶进度!

一、项目说明

项目需求:股吧中人们的言论行为和股市涨跌的延迟相关性
数据来源:、
数据字段:阅读、评论、标题、作者、更新时间
实现功能:读取每个公司股吧的全部页面的数据并写入excel表中

二、实施过程

以为例

1.明确获取网页中哪些数据

我们需要爬取的是东方财富吧中全部发帖信息的阅读评论标题作者最后更新时间这五个字段的数据,我一开始想也不是很难,解析一下网页匹配一下对应的标签值就可以了,但后面还是出现了各种各样的问题,需要大家注意一下。


2.查看网页源代码分析结构

① 网页源代码

首先打开网页的开发者工具(Ctrl+Shift+i),在源代码中查找对应字段的标签结构。


从图中可以看出,这五个字段分别位于行标签内,对应的属性分别是"l1 a1"、"l2 a2"、"l3 a3"、"l4 a4"、"l5 a5"。想必大家已经有思路了,我们可以通过先获取网页代码,再解析网页查询对应的五个字段,最后做一个提取就可以了。

② 网页链接

【东方财富吧:300059】
首页:
第二页:
可以看出个股吧链接主要由三部分组成:list、名称代码、页数

I.的数字代码


II. 翻页数据

如何得到不同股吧的所有翻页数据,着实让我找了好久,各种资源我都找了可惜还是没有发现,突然无意之中我找到了解决办法,我直接一个好家伙!

跟上述的五类字段一样,我们查看一下页数的代码字段,如下图所示:


我的第一个办法是直接解析网页后找到标签下的sumpage属性,其内容即为总页数,本来以为原来这么好获取,结果解析完才发现,pagernums里的内容是动态的,即span.on是会随页而变化的,故直接requests并不能获取到,但是还是被我发现了玄机!


大家可以看data-pager这里,里面的内容是list,300059_|452885|80|2,我对比了几个页面后发现其中数字分别代表的是:

300059:股吧数字代码452885:该股吧共发帖452885条
80:每个页面分别有80条贴子
2:当前所处页面为第2页

那么这时候,我们就可以直接用累积多年的算力(小学除法)算出东方财富吧共有452885/80=5661.0625,向上取整共5662页!如果你也脱口而出好家伙的话,请在屏幕下方打出来!


3.爬虫需要具备的功能

基本问题解决了,我们可以开始编写爬虫了。这部分不讲代码原理,只解释代码功能。自己也是小白,如果代码存在问题或不清楚的话,欢迎大家在下方留言,我一定及时回复。

① 获取网页源代码

defgetHTMLText(url):try:r=requests.get(url,timeout=30)r.raise_for_status()r.encoding=r.apparent_encodingreturnr.textexcept:print("获取网页内容失败!")

② 解析网页并提取数据字段

defparsePage(html):list=[]#我用的二维数组存储read=[]comment=[]title=[]author=[]time=[]try:#print(html)soup=BeautifulSoup(html,"html.parser")foreachinsoup.find_all('span','l1a1'):if'万'ineach.string:each.string=each.string[:-2]read.append(each.string)read=read[1:]#read[0]=='阅读'list.append(read)foreachinsoup.find_all('span','l2a2'):comment.append(each.string)comment=comment[1:]#comment[0]=='评论'list.append(comment)foreachinsoup.find_all('span','l3a3'):first=each.select('a:nth-of-type(1)')foriinfirst:i.find_all("a")#print(i.title)title.append(i.title)list.append(title)foreachinsoup.find_all('span','l4a4'):first=each.select('font:nth-of-type(1)')foriinfirst:i.find_all("font")#print(i.title)author.append(i.title)list.append(author)foreachinsoup.find_all('span','l5a5'):time.append(each.string)time=time[1:]#time[0]=='最后更新'list.append(time)except:print("解析网页字段失败!")returnlist

③ 获取贴吧总页数

基于解析的网页直接find_all也是可以的
defget_total_pages_num(url):try:chrome_options=webdriver.ChromeOptions()chrome_options.add_argument('--headless')chrome_options.add_argument('lang=zh_CN.UTF-8')chrome_options.add_argument('User-Agent="Mozilla/5.0(Macintosh;IntelMacOSX10_12_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/65.0.3325.162Safari/537.36"')chrome_options.add_argument('--disable-extensions')chrome_options.add_argument('--disable-gpu')chrome_options.add_argument('--no-sandbox')driver=webdriver.Chrome(options=chrome_options)driver.get(url)page_data=driver.find_element_by_xpath('//div[@id="mainbody"]/div[@id="articlelistnew"]/div[@class="pager"]/span[@class="pagernums"]').get_attribute('data-pager')#print(page_data)ifpage_data:#page_nums=re.findall('\|(\d+)',page_data[0])page_nums=page_data.split("|")#print(page_nums)total_pages=math.ceil(int(page_nums[1])/int(page_nums[2]))driver.quit()exceptExceptionase:total_pages=1returnint(total_pages)

4.爬取结果

上述代码基本的字段已经可以实现爬取了,结果如下:


可以看到,我这里的时间多了年份,这是由于朋友研究的需要,在基于一次爬取的结果上,进行二次爬取标题所带的链接网页获得的,有关二次爬取的内容,我们再下一节再和大家分享。


总结

在爬取过程中,我还遇到了很多问题诸如:
① 部分帖子结构不同或存在冗余该如何处理(问董秘等链接)
② 爬取过程中ip被屏蔽自动跳转页面该如何处理(代理IP池)
… …
这些内容在后续章节中再和大家分享,下期再见啦!

你可能想看:

有话要说...

取消
扫码支持 支付码