数据分析和数据可视化阶段性总结 (一)

最近有接手数据项目, 这两个项目有个共同点就是看上去都特别简单, 以为三两个小时就可以搞定, 但实际上里面的坑却特别多。 不完整做一遍, 只是在表面上理解完全不会体会到那种踩坑改bug的地狱般无助的感觉。

《黑客与画家》里说到, 一流的高手写代码都特别流畅, 一般思路对了, 不会关bug 什么事, 总是改bug 是非常令人羞耻的行为。不过还好本人对自己的编程能力要求不高, 也就做一下自己这方面的总结, 希望牛人不要光顾我的博客:)

我有一个习惯, 就是喜欢反复琢磨一个项目, 从里面挖掘出这个项目的通用解决方法和框架, 以后做的项目, 都在这个基础上进行改良和升级。所以这篇博客讲一下在写代码时遇到的卡点以及之后的改良。

题目大致方向: 采集中国理财网存续的理财产品信息。

其实是采集筛选类型下的其中一个叫存续的圆圈选项,出来一张表格, 一共有1546页。

卡点一: 发现此网站保密性工作做的极好,网站禁止右键

解决方法: 查了无数禁止右键的博客, 找到了正确的解决方法:书签法 - 在chrome 中输入一个书签, 名称栏输入【解除右键限制】, 网址处输入:

javascript:(function() { function R(a){ona = "on"+a; if(window.addEventListener) window.addEventListener(a, function (e) { for(var n=e.originalTarget; n; n=n.parentNode) n[ona]=null; }, true); window[ona]=null; document[ona]=null; if(document.body) document.body[ona]=null; } R("contextmenu"); R("click"); R("mousedown"); R("mouseup"); R("selectstart");})()

保持为书签, 回到网站,点击书签“【解除右键限制】”,网页上即可右键。

卡点二: 在headers里, 看到request method 是post 不是get

解决方法:当写完了代码,经过多方排除,发现获取到的数据什么也没有,就查看request 的语句到底有什么问题。知道post 的方法后,知道preview 里不再是prementer,而是form data. 修改为:

res = requests.post(url, headers=headers, data = json.dumps(FormData))

卡点三: 出现一个报错。AttributeError: ‘set’ object has no attribute 'items’.

解决方法: headers= {‘User-Agent’ : ‘value’ } 而不是 headers= {‘User-Agent : value’ }url='https://www.chinawealth.com.cn/LcSolrSearch.go'    url 必须加引号。

卡点四: 爬虫时用requests解析到的内容与原网页内容不一致。

解决方法: 在尝试在headers 里加入cookie, host , referer 之后仍然没有解决问题。

headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
'Cookie':'BIGipServerPool_SuperFusion_LiCai_Nginx_8080=!U0gH0cZ/zj/u6zTw/RB9YiZAVIlwUwMdvUFcBfYQk4V8SlUpU1mLYC2XWsn3q6BpQUlLHx7DEIykIrY=; BIGipServerPool_SuperFusion_LiCai_fe_8080=2802057494.36895.0000; JSESSIONID=68036A67BB270B345BF228AAFC99FBBF; _pk_ses.3.8bc7=*; _pk_id.3.8bc7=e467ba032a815a22.1660469265.1.1660469266.1660469265.; _pk_ses.12.8bc7=*; _pk_id.12.8bc7=6cd8e9027d705fba.1660469267.1.1660469441.1660469267.',
'Host': 'www.chinawealth.com.cn',
'referer':'https://www.chinawealth.com.cn/zzlc/jsp/lccp.jsp' }

之后想到用selenium 模块。 先附常规解题法

import requests
import csv
import json
csv_file = open('存储产品.csv','w', newline = '', encoding = 'utf-8')
writer = csv.writer(csv_file)
list2 = ['产品名称','登记编码','期限类型','业绩比较基准下限(%)']
writer.writerow(list2)
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
'Cookie':'BIGipServerPool_SuperFusion_LiCai_Nginx_8080=!U0gH0cZ/zj/u6zTw/RB9YiZAVIlwUwMdvUFcBfYQk4V8SlUpU1mLYC2XWsn3q6BpQUlLHx7DEIykIrY=; BIGipServerPool_SuperFusion_LiCai_fe_8080=2802057494.36895.0000; JSESSIONID=68036A67BB270B345BF228AAFC99FBBF; _pk_ses.3.8bc7=*; _pk_id.3.8bc7=e467ba032a815a22.1660469265.1.1660469266.1660469265.; _pk_ses.12.8bc7=*; _pk_id.12.8bc7=6cd8e9027d705fba.1660469267.1.1660469441.1660469267.',
'Host': 'www.chinawealth.com.cn',
'referer':'https://www.chinawealth.com.cn/zzlc/jsp/lccp.jsp' }
url='https://www.chinawealth.com.cn/LcSolrSearch.go'
for i in range(1546):
    FormData = {
       'cpjglb':'None', 
       'cpyzms':'None',
       'cptzxz':'None',
       'cpfxdj':'None',
       'cpqx': 'None',
       'mjbz': 'None',
       'cpzt': '04',
       'mjfsdm':' 01','NA'
       'cpdjbm':'None',
       'cpmc': 'None',
       'cpfxjg':'None', 
       'yjbjjzStart':'None', 
       'yjbjjzEnd': 'None',
       'areacode':'None', 
       'pagenum':'str(i+1)',
       'orderby':'none', 
       'code': 'none'
    }
    res = requests.post(url, headers=headers, data = json.dumps(FormData))
    print(res.status_code)
    articles =res.json()
    print(articles) 
    lists = articles['List'] 
    for i in lists:
        list1 = [i['cpms'],i['cpdjbm'],i['qxms'],i['yjbjjzxx']]
        writer.writerow(list1)
csv_file.close()
print('okay')

  卡点五: selenium 安装不上。输入pip install selenium 一直断联

解决方法: 进入 pypi.org/,  在下载页面下载whl 文件, 在终端输入 

pip install /Users/apple/Desktop/selenium-4.4.3-py3-none-any.whl 
Processing ./Desktop/selenium-4.4.3-py3-none-any.whl

也就是把桌面上的whl 文件拖入install 后面, 安装成功。

给出初步selenium 代码,爬取网页表格数据。

卡点六:出现bug, FileNotFoundError: [Errno 2] No such file or directory: 'chromedriver': 'chromedriver'

解决方法: 提示没有chromedriver.exe(谷歌浏览器驱动)这个文件, chrome driver没有放置在正确的路径下。 下载chromedriver  http://chromedriver.storage.googleapis.com/index.html

打开终端 输入

open /usr/local/bin/

将下载到的chromedriver拷贝进去, 给chromedriver 运行权限, 输入apple password

sudo chmod u+x,o+x   /usr/local/bin/chromedriver

看安装的版本号

chromedriver --version

出现bug , 打不开 chromedriver?

输入代码

cd /usr/local/bin/

打开隐私模式, 增加信任

xattr -d com.apple.quarantine chromedriver

再次输入看完装的版本号, 就可以了。

把chromedriver 的完整路径用终端提取出来, 把文件拖入终端

 /usr/local/bin/chromedriver 

最后在webdriver中加入chromedriver的路径,彻底解决找不到chromedriver的路径的问题。

附上五种方法,教你如何在Mac上查看文件完整路径 - 百度文库

browser = webdriver.Chrome('/usr/local/bin/chromedriver') 

卡点七:解决DeprecationWarning: Executable executable_path has been deprecated, please pass in a Service object in Selenium Python  
解决方式: 该类型的警告大多属于版本更新时,所使用的方法过时的原因;某方法在当前版本被重构,依旧可以传入参数,但是在之后的某个版本会被删除。

写入代码, 问题解决

import csv
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

chrome_options = Options() 
chrome_options.add_argument('--headless')
s = Service(executable_path=r'/usr/local/bin/chromedriver')
driver = webdriver.Chrome(service = s ,options = chrome_options)

初步selenium 代码

import csv
from selenium import webdriver
import time
from selenium.webdriver.chrome.service import Service

s = Service(executable_path=r'/usr/local/bin/chromedriver')
driver = webdriver.Chrome(service = s)
csv_file = open('存续产品.csv','w', newline = '', encoding = 'utf-8')
writer = csv.writer(csv_file)

driver.get('https://www.chinawealth.com.cn/zzlc/jsp/lccp.jsp')
def GetTableElements():
    driver = GetDriver()
    elements = driver.find_elements_by_tag_name('table')
    return elements

def _GetHeadList(table):
    trs = elements.find_elements_by_tag_name('tr').find_elements_by_class_name('pro_title')
    res1 =[]
    for tr in trs:
        res1.append(tr.text)
    return res1
           

def _GetOneRow(tr, heads):
    res2={}
    tds = tr.find_elements_by_tag_name('td')
    for i, td in enumerate(tds):
        res2[heads[i]]= td
    return res2 

def GetTable(table):
    res3 =[]
    heads = _GetHeadList(table) 
    tbody = table.find_element_by_tag_name('tbody')
    trs = tbody.find_elements_by_tag_name('tr')
    for tr in trs:
        row = _GetOneRow(tr, heads) 
        res3.append(row)
    return res3
    writer.writerow(res3) 

csv_file.close()
driver.close()    

卡点八: 输出的csv文档空白,

解决方式: 通过排查,发现是函数的代码无法输出结果,换一种代码方式。我们看到table 类型的网页结构大概是这样。 

<table class="..." id="...">
    <thead>
    <tr>
    <th>...</th>
    </tr>
    </thead>
    <tbody>
        <tr>
            <td>...</td>
        </tr>
        <tr>...</tr>
        <tr>...</tr>
        <tr>...</tr>
        <tr>...</tr>
        ...
        <tr>...</tr>
        <tr>...</tr>
        <tr>...</tr>
        <tr>...</tr>        
    </tbody>
</table>

通过pandas 来做。

import csv
from selenium import webdriver
import pandas as pd
from selenium.webdriver.chrome.service import Service

s = Service(executable_path=r'/usr/local/bin/chromedriver')
driver = webdriver.Chrome(service = s)
csv_file = open('存续产品.csv','w', newline = '', encoding = 'utf-8')
writer = csv.writer(csv_file)

driver.get('https://www.chinawealth.com.cn/zzlc/jsp/lccp.jsp')
datalist=[]
header=[i for i in driver.find_elements_By.cssSelector("table>tr>pro_title")if i.text],
rows=[i for i in driver.find_elements_By.cssSelector("tbody>tr") if i.text]
for row in rows:													 
  datalist.append([i for i in row.find_elements_By.cssSelector("td") if i.text])
  df=pd.DataFrame(datalist,index=header)
  writer.writerow(df)
csv_file.close()
driver.close()    

卡点九: WebDriver‘ object has no attribute ‘find_element_by'

解决方法: find_element_by 语法错误, 更换语法。 

driver.get('https://www.chinawealth.com.cn/zzlc/jsp/lccp.jsp')
datalist=[]
header=[i for i in driver.find_element(By.CSS_SELECTOR,"#table>tr>pro_title")if i.text],
rows=[i for i in driver.find_elements(By.CSS_SELECTOR,"#tbody>tr") if i.text]
for row in rows:													 
  datalist.append([i for i in row.find_elements(By.CSS_SELECTOR,"td") if i.text])
  df=pd.DataFrame(datalist,index=header)
  writer.writerow(df)

卡点十:  no such element: Unable to locate element: {"method":"css selector","selector":"#table>tr>pro_title"}

解决方案: 重新复习标签,属性和元素, 复习css_selector 的用法。修改header 等代码。

datalist=[]
header =[i for i in driver.find_element(By.CSS_SELECTOR,"#tbody>tr['class = pro_title']")if i.text],
rows=[i for i in driver.find_elements(By.CSS_SELECTOR,"#tbody>tr") if i.text]
for row in rows:													 
  datalist.append([i for i in row.find_elements(By.CSS_SELECTOR,"td") if i.text])
  df=pd.DataFrame(datalist,index=header)
  writer.writerow(df)

卡点十一: selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified.    

解决方案; 表达错误, 重新表达

datalist=[]
header =[i for i in driver.find_element(By.CSS_SELECTOR,'tbody>tr[class = 'pro_title']')if i.text],
rows=[i for i in driver.find_elements(By.CSS_SELECTOR,'tbody>tr') if i.text]
for row in rows:													 
  datalist.append([i for i in row.find_elements(By.CSS_SELECTOR,'td') if i.text])
  df=pd.DataFrame(datalist,index=header)
  writer.writerow(df)
csv_file.close()

卡点十二: selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: 'value' must be a string.

解决方案:注意class 属性的定位方法, 参照 小红书,CssSelector定位详解 - 百度文库Selenium之find_element_by_css_selector()的使用方法 - 灰信网(软件开发博客聚合)发现多标签层次和class=pro_title 的用法 以及value is string的解决方法为 'tbody>tr.pro_title'

import csv
from selenium import webdriver
import pandas as pd
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By


s = Service(executable_path=r'/usr/local/bin/chromedriver')
driver = webdriver.Chrome(service = s)
csv_file = open('存续产品.csv','w', newline = '', encoding = 'utf-8')
writer = csv.writer(csv_file)

driver.get('https://www.chinawealth.com.cn/zzlc/jsp/lccp.jsp')
datalist=[]
header =[i for i in driver.find_element(By.CSS_SELECTOR,'tbody>tr.pro_title')if i.text]
rows=[i for i in driver.find_elements(By.CSS_SELECTOR,'tbody>tr') if i.text]
for row in rows:													 
  datalist.append([i for i in row.find_elements(By.CSS_SELECTOR,'td') if i.text])
  df=pd.DataFrame(datalist,index=header)
  writer.writerow(df)
csv_file.close()
driver.close()

网站显示故障。 但是代码目测大概率正确。 

任务基本完成。 最后总结一句: 只有做对了, 才能享受其中!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值