蟲是一件很有趣的事情,就像黑客一樣,和服務器對抗,服務器維護代碼防止爬蟲,我們通過各種bug解決爬蟲困難,真實有趣!今天給大家帶來一串代碼,針對網頁中的表格爬取,表格頁碼變化,而鏈接url不變的情況1
首先給出爬取的原文鏈接:https://d.qianzhan.com/yuanqu/
#導入所需庫文件 import requests import pandas as pd import csv
上面三個庫文件是本次爬蟲所需的主要庫,requests庫向網站發送請求,請求成功則返回響應狀態碼為200,否則為400或者404,pandas庫可以用來直接抓取表格數據,csv庫用來將文件保存在本地csv文件內。
#這里爬取的表格為廣東省的數據表格 areas = ['廣東省'] #寫入鏈接url urls = ['https://d.qianzhan.com/yuanqu/?p={}'.format(str)for str in areas] x = 0 for url in urls: #打開csv文件,在第一行寫入標題 with open('前瞻.csv', 'a', newline='', encoding='utf-8-sig') as csvfile: w = csv.writer(csvfile) # 寫入標題或稱之為變量 w.writerow(['序號', '園區名稱', '省份', '城市', '占地面積', '企業數', '詳情']) # 對表格的全部頁數進行抓取 for i in range(1, 33): # 跳頁 # 在網頁源代碼找到頁碼的屬性,這里頁碼在屬性page上 data = { 'page': i } # 對網站發送請求,獲得響應 s = requests.session() d = s.get(url, params=data) # 抓取html表格 tb = pd.read_html(d.text)[1] # 將抓取來的表格填入csv文件內 tb.to_csv(r'前瞻.csv', mode='a', encoding='utf_8_sig', header=0, index=0) # 每抓取玩一個省份,打印出抓取結果,給用戶更好體驗 print(areas[x], "已經抓取完成!請到本地文檔中查看抓取結果!") x = x+1 # 全部抓取完成,則打印'全部抓取完畢!' print('全部抓取完畢!')
最終成功抓取到所有表格的內容,并存入了csv文件內,大家有問題可以下方留言討論!
某網站讀取表格里面的內容,簡單處理后寫入CSV文件。需要留意:查找某些字符是否存在,查找其位置,按照位置讀取字符串內容,Python真的蠻靈活的。后續還會做兩個文件的比較,以及文件內容的刪除。讓已實現的功能具有普適性,抽取函數供不同場景使用,這才有軟件工程的思想。
實踐Python
fileName = "SplitNo";
nowTime = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
filePath = fileName + nowTime + ".csv";
csvFile = open(filePath, 'w', newline='', encoding='utf-8')
writer = csv.writer(csvFile,dialect='excel')
head = ["頁數","序號","編號", "產品名稱", "原始文本"]
writer.writerow(head)
startPage = 1;
totalPage = 1260;
wait.until(EC.presence_of_element_located((By.ID, "content")))
browser.find_element_by_id("page").clear()
browser.find_element_by_id("page").send_keys(str(startPage));
browser.find_elements_by_xpath('//input[@src="images/dataanniu_11.gif"]')[0].click();
time.sleep(3)
n = startPage;
while n < totalPage:
wait.until(EC.presence_of_element_located((By.ID, "content")))
content = browser.find_element_by_id("content");
oneThanOneLine = False;
for attr in content.find_elements_by_tag_name("a"):
text = str(attr.get_attribute('innerHTML'))
text = text.replace('\r', '').replace('\n', '').replace('\t', '')
print(str(text) + "查詢位置:" + (str)(text.find(".")))
if text.find(".") != -1:
csvRow = []
csvRow.append(str(n))
pos = findPos(text)
if pos != -1:
name = text[0:pos-1]
notext = text[pos:-1]
csvRow.append(name.split(".")[0])
csvRow.append(notext.split(" ")[0])
if name.__len__() > 1:
csvRow.append(name.split(".")[1])
csvRow.append(text)
writer.writerow(csvRow)
preText = text
oneThanOneLine = False
else:
preText = preText + text;
#p = re.compile(r'[<](.*?)[>]', re.S)
# matches = re.findall(cleanr, preText)\
#for match in matches:
# print(match)
cleanr = re.compile('<.*?>')
preText = re.sub(cleanr, '', preText)
print(preText)
oneThanOneLine = True
n = n + 1
wait.until(EC.presence_of_element_located((By.ID, "page")))
browser.find_element_by_id("page").clear()
browser.find_element_by_id("page").send_keys(str(n))
browser.find_elements_by_xpath('//input[@src="images/xxxx.gif"]')[0].click()
print("已經切換到新一頁:" + str(n))
csvFile.close()
browser.close()
碰到的問題:
1、TypeError: expected string or bytes-like object
使用場景:content = browser.find_element_by_id("content");
tdList = re.findall(r'<td[^>]*>(.*?)</td>', str(content.get_attribute('innerHTML')), re.I | re.M)
if tdList:
for item in tdList:
print(item)
使用函數:re.findall(pattern,string,flag)
pattern匹配的是字符串,需要把第二個參數轉化為string類型就可以。
2、對循環列表的最后一個元素進行特別處理
使用場景:aTag = attr.find_elements_by_tag_name("a")
if aTag.__len__()>1:
for aText in aTag:
if aTag.__len__() - 1 == aTag.index(aText):
print(aText )
3、超時跳轉使用wait元素比較靠譜些
wait.until(EC.presence_of_element_located((By.ID, "content")))
print(str(n) + "img[@src='images/dataanniu_07.gif'])")
content = browser.find_element_by_id("content");
content.find_elements_by_xpath('//img[@src="images/dataanniu_07.gif"]')[0].click();'''
4、查詢某字符串里面的HTML字符
p = re.compile(r'[<](.*?)[>]', re.S)
matches = re.findall(p, preText)
for match in matches:
print(match)
5、清除某字符串里面的HTML字符
cleanr = re.compile('<.*?>')
preText = re.sub(cleanr, '', preText)
6、記錄程序執行時間
import datetime
startTime = datetime.datetime.now()
endTime = datetime.datetime.now()
print(endTime - startTime).seconds
7、等待元素的方法
隱式等待:(WebDriver類下的)implicitly_wait(X),在X時間內,頁面加載完成,進行下一步操作。首先Implicit Waits默認是等待時間是0,同時隱性等待是對driver起作用,所以只要設置一次即可,比強制等待更智能
缺點:非要加載到整個頁面才能執行代碼,這樣影響代碼的執行效率。一般情況下,我們想要的結果是只需加載到了我要定位的元素就執行代碼,不需要等待整個頁面的完全加載出來再執行代碼。
Sleep顯式等待:最簡單的一種辦法就是強制等待sleep(X),強制讓瀏覽器等待X秒,不管當前操作是否完成,是否可以進行下一步操作,都必須等X秒的時間。
缺點是不能準確把握需要等待的時間;優點是使用簡單,可以在調試時使用。
WebDriverWait顯示等待:無需等待整個頁面加載完成,只需加載到你要定位的元素就可以執行代碼。
優點:代碼執行效率快。是最智能的設置元素等待的方式。
缺點:需要導入webdriver下的expected_conditions、WebDriverWait、By三個包;寫等待時間的代碼稍顯復雜。
python的matplotlib作圖很強大,本文教你用6種不同方式解決將多種數據曲線畫到一起。
今天,老板又要一個數據報表,小明選擇用 python來實現。“用matplotlib用來可視化。并且必須用不同顏色標志每個數據曲線,曲線這些顏色也應該在Python里自動選擇。”
"Python大大,你能給我一個方法,在同一個圖中為不同的地塊添加不同的顏色嗎?",小明把這個問題拋給了Python大大。大大低頭片刻,然后胸有成足的抬起頭,說,“可以,給你6個辦法來實現!!”
煩惱如何用python可視化多條數據曲線嗎?本文提供6種解法
利用Matplotlib的默認方式來執行此操作。
例如:
import matplotlib.pyplot as plt import numpy as np x = np.arange(10) plt.plot(x, x) plt.plot(x, 2 * x) plt.plot(x, 3 * x) plt.plot(x, 4 * x) plt.show()
而且,正如您可能已經知道的那樣,您可以輕松添加圖例:
import matplotlib.pyplot as plt import numpy as np x = np.arange(10) plt.plot(x, x) plt.plot(x, 2 * x) plt.plot(x, 3 * x) plt.plot(x, 4 * x) plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left') plt.show()
如果要控制將循環的顏色:
import matplotlib.pyplot as plt import numpy as np x = np.arange(10) plt.gca().set_color_cycle(['red', 'green', 'blue', 'yellow']) plt.plot(x, x) plt.plot(x, 2 * x) plt.plot(x, 3 * x) plt.plot(x, 4 * x) plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left') plt.show()
希望有所幫助!如果您對matplotlib不熟悉。請關注微信python_dada學習。
首先,如果你想要在一個圖上上繪制很多數據曲線,可以:
1. 將它們放在不同的圖上(考慮在一個圖上使用一些子圖),或
2. 使用顏色以外的其他東西(即標記樣式或線條粗細)來區分它們。
否則,你將陷入一個非常混亂的境地!
除此之外,許多人在不同程度上都是色盲,區分眾多微妙不同的顏色對于更多的人來說比你可能意識到的要困難。
話雖如此,如果你真的想在一個軸上放20條線,并且有20種相對不同的顏色,這是一種方法:
import matplotlib.pyplot as plt import numpy as np num_plots = 20 # Have a look at the colormaps here and decide which one you'd like: # http://matplotlib.org/1.2.1/examples/pylab_examples/show_colormaps.html colormap = plt.cm.gist_ncar plt.gca().set_color_cycle([colormap(i) for i in np.linspace(0, 0.9, num_plots)]) # Plot several different functions... x = np.arange(10) labels = [] for i in range(1, num_plots + 1): plt.plot(x, i * x + 5 * i) labels.append(r'$y = %ix + %i$' % (i, 5*i)) # I'm basically just demonstrating several different legend options here... plt.legend(labels, ncol=4, loc='upper center', bbox_to_anchor=[0.5, 1.1], columnspacing=1.0, labelspacing=0.0, handletextpad=0.0, handlelength=1.5, fancybox=True, shadow=True) plt.show()
請注意,對于最后一個示例,在較新版本的matplotlib中,set_color_cycle已棄用,因此該行應該plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))只是plt.cm.YOUR_PREFERED_COLOR_MAP根據您的需要進行更改。 -
如果您不知道要繪制的繪圖的數量,可以在繪制它們直接從繪圖中檢索數字后更改顏色.lines,使用此解決方案:
一些隨機數據
import matplotlib.pyplot as plt import numpy as np fig1 = plt.figure() ax1 = fig1.add_subplot(111) for i in range(1,15): ax1.plot(np.array([1,5])*i,label=i)
您需要的代碼段:
colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired colors = [colormap(i) for i in np.linspace(0, 1,len(ax1.lines))] for i,j in enumerate(ax1.lines): j.set_color(colors[i]) ax1.legend(loc=2)
結果如下:
我想對上一篇文章中給出的最后一個循環答案提供一個小的改進(該帖子是正確的,仍然應該被接受)。標記最后一個示例時所隱含的假設是plt.label(LIST)將標簽號X放入LIST與第X 個時間對應的行中plot。我之前遇到過這種方法的問題。根據matplotlibs文檔()構建圖例和自定義標簽的推薦方法是讓人有一種溫暖的感覺以及您認為他們所做的確切情節:
...
# Plot several different functions... labels = [] plotHandles = [] for i in range(1, num_plots + 1): x, = plt.plot(some x vector, some y vector) #need the ',' per ** below plotHandles.append(x) labels.append(some label) plt.legend(plotHandles, labels, 'upper left',ncol=1) **:
圖(axes)中的每個plot()figure都有自己的顏色循環 - 如果不為每個繪圖強制使用不同的顏色,則所有繪圖都共享相同的顏色順序。
只有當我們伸展 "自動"意味著什么時,才能自動實現每個繪圖中的不同顏色。
必須使用不同的顏色識別每個繪圖,這些顏色應該由[Matplotlib]自動生成。
但是...... Matplotlib會自動為每條不同的曲線生成不同的顏色
In [10]: import numpy as np ...: import matplotlib.pyplot as plt In [11]: plt.plot((0,1), (0,1), (1,2), (1,0)); Out[11]:
你能給我一個方法,在同一個圖中為不同的地塊添加不同的顏色嗎?
它是有道理的,因為每個繪圖(每個axes在Matplotlib的用語中)都有自己的color_cycle(或者更確切地說,在2018年,它的prop_cycle),每個plot(axes)以相同的順序重用相同的顏色。
In [12]: fig, axes = plt.subplots(2,3) In [13]: for ax in axes.flatten(): ...: ax.plot((0,1), (0,1))
如果這是原始問題的含義,一種可能性是為每個圖明確命名不同的顏色。
如果在循環中生成繪圖(通常發生),我們必須有一個額外的循環變量來覆蓋Matplotlib 自動選擇的顏色。
In [14]: fig, axes = plt.subplots(2,3) In [15]: for ax, short_color_name in zip(axes.flatten(), 'brgkyc'): ...: ax.plot((0,1), (0,1), short_color_name)
另一種可能性是實例化循環器對象
from cycler import cycler my_cycler = cycler('color', ['k', 'r']) * cycler('linewidth', [1., 1.5, 2.]) actual_cycler = my_cycler() fig, axes = plt.subplots(2,3) for ax in axes.flat: ax.plot((0,1), (0,1), **next(actual_cycler))
請注意,type(my_cycler)是cycler.Cycler,但是type(actual_cycler)是itertools.cycle。
本文以python的matplotlib作圖為例,用6種方法解決了同時繪制不同數據曲線的問題。
不僅僅體現了python可視化能力的強大,也對拓寬大家的思路做了一定的嘗試。希望大家喜歡。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。