本文做者:魏泯html
博客源地址:https://www.cnblogs.com/simple/python
作有效率的魔法師sql
*跳轉到文章結尾*
mongodb
爬蟲就是 模擬瀏覽器發送網絡請求,獲取響應,按照規則提取數據的程序。爬蟲要的就是保存數據,只抓取不保存毫無用處。chrome
Url:須要進行解碼或轉碼
爬蟲和瀏覽器請求的URL地址有必定差異。Elements與Network中的源碼會不同。數據庫
Http:超文本傳輸協議:以明文方式進行傳輸,效率更高。
Https:Http+SSL(安全套接字層):傳輸數據以前,將數據加密,以後解密,效率較低,可是更安全。json
這二者都包含請求與響應部分。瀏覽器
Http報文請求由三部分組成:請求行、請求頭、請求體緩存
Status code:狀態碼
Conection: keep-alive 支持長鏈接
Cache-Control:max-age=0 緩存控制爲零
User-Agent:瀏覽器(內核)身份標識
Upgrade-Insecure-Requests:支持將不安全請求轉換的功能
Accept:表示我想接收什麼數據,q=權重
Cookie:瀏覽器保存在用戶本地的一些信息,包括用戶密碼,帳號信息,網站校驗信息(例如csrf跨站保護)。會被攜帶發送給服務器。Cookie能夠被服務器用來判斷客戶端是不是爬蟲。
Query-String-Parameters:請求數據(GET)
From-data:請求數據(POST)
能夠在Chorme中模擬多種版本的機器安全
GET請求沒有請求體,數據放在URL中
POST請求有請求體:攜帶數據,參數放置於請求體中,經常使用於登錄註冊、傳輸大文本。
requests模塊是一個第三方包:用於模擬http數據請求。
在接下來的內容裏咱們學習一下它的多種請求。
requests方式比urlib方式簡單
50%的動態內容是json格式的數據。
Http請求的get的請求方式:
使用這種方式獲得一個響應對象
url = "http://www.baidu.com/" response = requests.get(url=url)
Terminal:
<Response [200]>
使用這種方式獲得一個響應對象
url = "http://www.baidu.com/" data = {鍵:"值"} response = requests.get(url=url,data=data)
Terminal:
<Response [200]>
headers是一個Hash字典,以鍵值的方式存放頭部信息。
例如:
headers={"鍵":"值,} response = requests.get(url=url, headers=headers)
除了url和之外還有不少參數,好比timeout、代理IP等等
配合異常捕獲,在指定時間返回響應
# 在三秒內必須返回響應,不然則會報錯 response = requests.get(url=url,headers=headers,timeout=3)
proxies = [{"http":"113.122.8.45:53128"},{"http":"114.122.8.45:53128"},{"http":"115.122.8.45:53128"}]
proxy = random.choice(proxies)
經過response
獲取頁面的響應內容,包括響應頭、響應體。
這是咱們所使用的公共代碼:
import requests url = 'https://www.cnblogs.com/Asterism-2012/' response = requests.get(url=url)
print(response.content)
Terminal:
b'\r\n<!DOCTYPE html>\r\n<html lang="zh-cn">\r\n<head>\r\n<meta ......略
咱們發現剛纔打印的content內容是byte,爲了便於觀看,進行解碼:
它會將content的內容解碼爲str
類型,也能夠自行指定解碼類型。
x = response.content.decode() print(type(x)) print(x)
Terminal:
<class 'str'> 略......<p>by: 魏泯</p><!--PageEndHtml Block End--></body></html>
decode()自行指定content解碼類型:
x= response.content.decode('utf-8') print(type(x))
Terminal:
<class 'str'>
使用text
方法獲取到的源代碼,是根據HTTP 頭部對響應的編碼做出有根據的推測,推測的文本編碼。這種方法簡單經常使用,適用於大部分的網站。固然既然是推測的代碼,就也有出現錯誤的時候,這也不要緊,到時候咱們能夠經過指定編碼來解決這個問題。
print(response.text)
Terminal:
略......<p>by: 魏泯</p><!--PageEndHtml Block End--></body></html>
可是有的時候即使進行了解碼,也沒法正常看到頁面源碼。形成這樣的緣由是本地編碼與服務器編碼不統一,因此咱們要對響應回來的內容制定編碼。
response.encoding = response.apparent_encoding
response.encoding=」gbk」
有時候咱們須要獲取到目標站點的url,用於拼接新的url或者作保存、跳轉等工做,因此就用到了response.request.url
這個方法
x = response.request.url
Terminal:
https://www.cnblogs.com/Asterism-2012/
響應的url地址,有時候會由於跳轉而和請求目標地址不一致,使用response.url
方法來獲取它:
x = response.url print(x)
Terminal:
https://www.cnblogs.com/Asterism-2012/
有時候咱們須要測試本身的代理IP池、Header池信息,就能夠經過這個方法來動態獲取頭部信息進行查看
x = response.request.headers print(x)
Terminal:
{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
x = response.headers print(x)
Terminal:
{'Date': 'Fri, 04 Jan 2019 03:53:18 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'Cache-Control': 'private, max-age=10', 'Expires': 'Fri, 04 Jan 2019 03:53:28 GMT', 'Last-Modified': 'Fri, 04 Jan 2019 03:53:18 GMT', 'X-UA-Compatible': 'IE=10', 'X-Frame-Options': 'SAMEORIGIN', 'Content-Encoding': 'gzip'}
headers = {"Referver":"URL","User-Agent":"瀏覽器信息","Cookie":"..."}
# Cookie字符串 CookieStr = "anonymid=jm5lz4q0wv29sz; depovince=BJ; _r01_=1; JSESSIONID=abcpoYHrUXJZa6yQOiLxw; ick_login=4c5c0781-d37e-44c5-98a7-8e3fee81d222; ick=e74b83d4-c258-4de9-bd6c-3426f777fadd; XNESSESSIONID=949847ff1bf9; jebe_key=38dc9339-f175-472f-9288-02e4e7e4b59c%7Cd931901a60720bfd1a4f2f38c98639f3%7C1537147847212%7C1%7C1537147849534; wp_fold=0; jebecookies=054ec649-ffed-4989-beda-1be907785a33|||||; _de=BA25AEE63DF6B7A91E89E9A775AD2FBD; p=5929761e2707b622b09b23f92b3c04aa8; first_login_flag=1; ln_uact=15661592012; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; t=aaf1d9103cf916e1d824260c832ceaf38; societyguester=aaf1d9103cf916e1d824260c832ceaf38; id=968054908; xnsid=1acd462c; ver=7.0; loginfrom=null"
# 這是一個字典生成式,生成正式使用的Cookie Cookie = {i.split("=")[0]:i.split("=")[1] for i in CookieStr.split(";")} response = requests.get(url=url,headers=headers,cookies=Cookie)
import json
Py_data = json.loads(response.text)`
Js_data = json.dumps(Py_data)
Js_data = json.dumps(Py_data,ensure_ascii=False)
Js_data = json.dumps(Py_data,indent=2)
/html/head/meta
:可以選中html下的head下的全部的meta標籤//li
:當前頁面全部的li標籤/html/head/link//li
:表示meta下的全部li標籤//div[@class="father"]//li
: 獲取class名爲father的div下的全部li標籤//a/text()
:獲取a標籤中直接裸露的文本內容a//text()
:獲取a下的全部文本,包括子節點文本a/@href
:獲取a標籤中 href屬性中的內容
# 獲取詞語解釋 w_ex = html2.xpath('//*[@id="content"]/div[2]')[0].xpath("string(.)")
@後面跟屬性,若是放在方括號中,表明對所過濾的標籤集合進行過濾。若是放在url後,則表明獲取該屬性的值
etree.HTML(response.text)
# 將響應信息編碼改成網站制定編碼 response.encoding = response.apparent_encoding
dir = "directory" if not os.path.exsits(dir): pass
dir = "directory" os.mkdir(dir)
with("file_name","w+",encoding="utf-8") as f: f.write(content)
# 獲取返回響應信息頭部,這個不是很重要 for v,j in response.headers.items(): print(v,':',j) # 獲取請求信息頭部 for v,j response.request.headers.items(): print(v,':',j)
headers = { 'User-Agent':'僞造的瀏覽器內核信息' } response = requests.get(url=url,headers=headers)
headers = { 'Referer':'僞造的 上一級URL' } response = requests.get(url=url,headers=headers)
py_date = json.loads(response.text())
# 代理IP列表 proxies = [{"http":「133.12.45.12:8564」},{"協議":"IP:端口號"}] # random隨機選擇列表中的一個元素生成代理 proxy = random。choice(proxies) response = requests.get(proxies=proxy)
mongod.exe --dbpath C:\data\db(路徑) 指定服務地址
mongod(在環境變量下)
use DB_NAME
db.tb_name.insert({key:value})
show dbs;
db.dropDatabase()
db.createCollection("set_name")
show collections
db.collection.drop()
scrapy genspider x www.x.com
這裏使用的版本是1.0以上的版本,在填寫爬蟲域名的時候 不須要加引號
scrapy crawl x
>>>scrapy genspider -l Available templates: basic crawl csvfeed xmlfeed
爬蟲文件是整個框架中咱們最常編寫的,裏面包括一些內容須要咱們學習。
這裏的配置有不少,但並非咱們所學的所有,譬如分佈式設定,是要本身手寫進去的
# Obey robots.txt rules ROBOTSTXT_OBEY = False # default:True
# Override the default request headers: #DEFAULT_REQUEST_HEADERS = { # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 'Accept-Language': 'en', #}
# The initial download delay #AUTOTHROTTLE_START_DELAY = 5
#ITEM_PIPELINES = { # 'Csdnboke.pipelines.CsdnbokePipeline': 300, #}
# 導入模塊 from scrapy.exceptions import DropItem # 創建一個用於去重的類 class Set_it(object): # 創建一個構造方法 def __init__(self): self.set0 = set() # 創建一個process_item方法,它會自動調用 def process_item(self, item, spider): # 標題 title = item["title"] # 判斷標題是否已經存入了set中 if title in self.set0: # 將這條item記錄刪除,而且輸出一條提示信息 raise DropItem("這一條內容已經存在了,因此我把它刪了:%s"%title) # 不然將標題存入 else: # self.set0.add(title) return item
newspaper是一個第三方包,用於快速抓取頁面信息。它的開發團隊來自於美國,如今還仍在維護當中。若是要使用,首先要保證在你的電腦上下載並安裝這個包,對此,咱們可使用pip這樣的包管理器進行直接下載安裝,固然,用conda也能夠。
pip install newspaper3k
import newspaper
# 實例化Article # demo: # news = newspaper.Article() news = newspaper.Article(url=base_url,language='zh')
news.download() news.parse()
content = news.text
title = news.title
img = news.imges
retrying是一個第三方模塊,用於重試出現異常的函數。
首先進行安裝:
pip install retrying (安裝)
代碼示例(「出事了算個人,你儘管去作,作錯了也不怕,但最多三次」):
from retrying import retry # 做爲裝飾器 裝飾函數,報錯仍然重複執行,直到三次纔算出錯 @ retry(stop_max_attempt_number=3) def fun1(): print("hello world.") time.sleep(1) raise ValueError("This is a test error.")
#coding=utf-8 '''微型ORM v1.1 @help: 首先要保證你的items中的鍵值與數據庫中的字段吻合,其次要本身創建庫和數據表, 傳入你的item,而且傳入表的名稱 @Form: 魏泯 ''' def sql(item,table): ''' item: Your dict. table: Your table name. ''' # 生成兩個列表推導式 keylis = [key for key,values in item.items()] vlis = [values for key,values in item.items()] # 生成sql 語句中所須要的 str1215 = '"{}"'+',"{}"'*(len(item)-1) str1217 = '{}'+',{}'*(len(item)-1) str1216 = 'insert into '+table+'('+str1217+')'+' value ('+str1215+')' _sql = str1216.format(*keylis,*vlis) return _sql # 返回sql語句