日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

爬虫教程( 1 ) --- 初级、基础、实践

發(fā)布時(shí)間:2023/12/9 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 爬虫教程( 1 ) --- 初级、基础、实践 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

爬蟲(chóng)教程:https://piaosanlang.gitbooks.io/spiders/content/

如何入門(mén) Python 爬蟲(chóng)https://zhuanlan.zhihu.com/p/21479334

靜覓 崔慶才的個(gè)人博客 Python 爬蟲(chóng)系列:http://cuiqingcai.com/category/technique/python

http://www.cnblogs.com/miqi1992/category/1105419.html

Python 爬蟲(chóng)從入門(mén)到放棄系列博客:https://www.cnblogs.com/zhaof/tag/爬蟲(chóng)/default.html?page=2

Python 爬取功能匯總:https://www.jb51.net/Special/985.htm

Python 3.8.5 文檔

官方文檔:https://docs.python.org/zh-cn/3/

1. 爬蟲(chóng)入門(mén) 初級(jí)篇

IDE 選擇: PyCharm (推薦) 、SublimeText3、Visual Studio

Python 版本:Python3。( 最簡(jiǎn)單的是直接安裝 Anaconda,使用 Anaconda 管理虛擬環(huán)境?)

  • Windows 平臺(tái):https://docs.python.org/zh-cn/3/using/windows.html
  • Linux Ubuntu 平臺(tái):https://docs.python.org/zh-cn/3/using/unix.html

1.1 為什么要學(xué)習(xí)爬蟲(chóng)

學(xué)習(xí)需求:抓取的某個(gè)網(wǎng)站或者某個(gè)應(yīng)用的內(nèi)容,提取有用的價(jià)值

實(shí)現(xiàn)手段:模擬用戶(hù)在瀏覽器或者應(yīng)用(app)上的操作,實(shí)現(xiàn)自動(dòng)化的程序爬蟲(chóng)應(yīng)用場(chǎng)景(利用爬蟲(chóng)能做什么?)

大家最熟悉的應(yīng)用場(chǎng)景:搶票神器(360搶票器)、投票神器(微信朋友圈投票)

企業(yè)應(yīng)用場(chǎng)景

  • 拉勾網(wǎng)招聘職位數(shù)據(jù)分析報(bào)告
  • 2016年中國(guó)外賣(mài)O2O行業(yè)發(fā)展報(bào)告
  • 2016年中國(guó)在線出境游市場(chǎng)研究報(bào)告

1、各種熱門(mén)公司招聘中的職位數(shù)及月薪分布

2、對(duì)某個(gè) App 的下載量跟蹤

3、 飲食地圖

4、 票房預(yù)測(cè)

1.2 爬蟲(chóng)是什么 ?

專(zhuān)業(yè)術(shù)語(yǔ): 網(wǎng)絡(luò)爬蟲(chóng)(又被稱(chēng)為網(wǎng)頁(yè)蜘蛛,網(wǎng)絡(luò)機(jī)器人)是一種按照一定的規(guī)則,自動(dòng)的抓取萬(wàn)維網(wǎng)信息的程序或者腳本。

爬蟲(chóng)起源(產(chǎn)生背景):隨著網(wǎng)絡(luò)的迅速發(fā)展,萬(wàn)維網(wǎng)成為大量信息的載體,如何有效地提取并利用這些信息成為一個(gè)巨大的挑戰(zhàn);搜索引擎有Yahoo,Google,百度等,作為一個(gè)輔助人們檢索信息的工具成為用戶(hù)訪問(wèn)萬(wàn)維網(wǎng)的入口和指南。網(wǎng)絡(luò)爬蟲(chóng)是搜索引擎系統(tǒng)中十分重要的組成部分,它負(fù)責(zé)從互聯(lián)網(wǎng)中搜集網(wǎng)頁(yè),采集信息,這些網(wǎng)頁(yè)信息用于建立索引從而為搜索 引擎提供支持,它決定著整個(gè)引擎系統(tǒng)的內(nèi)容是否豐富,信息是否即時(shí),因此其性能的優(yōu)劣直接影響著搜索引擎的效果。

網(wǎng)絡(luò)爬蟲(chóng)程序的優(yōu)劣,很大程度上反映了一個(gè)搜索引擎的好差。不信,你可以隨便拿一個(gè)網(wǎng)站去查詢(xún)一下各家搜索對(duì)它的網(wǎng)頁(yè)收錄情況,爬蟲(chóng)強(qiáng)大程度跟搜索引擎好壞基本成正比。

搜索引擎工作原理

  • 第一步:抓取網(wǎng)頁(yè)(爬蟲(chóng))。搜索引擎是通過(guò)一種特定規(guī)律的軟件跟蹤網(wǎng)頁(yè)的鏈接,從一個(gè)鏈接爬到另外一個(gè)鏈接,像蜘蛛在蜘蛛網(wǎng)上爬行一樣,所以被稱(chēng)為“蜘蛛”也被稱(chēng)為“機(jī)器人”。搜索引擎蜘蛛的爬行是被輸入了一定的規(guī)則的,它需要遵從一些命令或文件的內(nèi)容。 ? ? ? Robots協(xié)議(也稱(chēng)為爬蟲(chóng)協(xié)議、機(jī)器人協(xié)議等)的全稱(chēng)是“網(wǎng)絡(luò)爬蟲(chóng)排除標(biāo)準(zhǔn)”(Robots Exclusion Protocol),網(wǎng)站通過(guò)Robots協(xié)議告訴搜索引擎哪些頁(yè)面可以抓取,哪些頁(yè)面不能抓取。
    robots.txt?示例:??https://www.taobao.com/robots.txt? ? ? ??http://www.qq.com/robots.txt
    示例:CSDN robot.txt ( https://blog.csdn.net/robots.txt ) 文件中 Sitemap: # -*- coding: UTF-8 -*-import re import requestsdef download(url, retry_count=3):html = Nonefor retry in range(retry_count):print(f'Downloading : {url}')custom_headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ''(KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36'}try:r = requests.get(url, headers=custom_headers, verify=False)if r.status_code == 200:print('status_code : {0}'.format(r.status_code))html = r.text # html = r.contentelse:print('status_code : {0}'.format(r.status_code))breakexcept BaseException as ex:print(f'Download error : {ex}')return htmlif __name__ == "__main__":temp_url = r'https://blog.csdn.net/s/sitemap/pcsitemapindex.xml'sitemap = download(temp_url)links = re.findall(r'<loc>(.*?)</loc>', sitemap)for link in links:print(link)pass
  • 第二步:數(shù)據(jù)存儲(chǔ)。搜索引擎是通過(guò)蜘蛛跟蹤鏈接爬行到網(wǎng)頁(yè),并將爬行的數(shù)據(jù)存入原始頁(yè)面數(shù)據(jù)庫(kù)。其中的頁(yè)面數(shù)據(jù)與用戶(hù)瀏覽器得到的 HTML 是完全一樣的。搜索引擎蜘蛛在抓取頁(yè)面時(shí),也做一定的重復(fù)內(nèi)容檢測(cè),一旦遇到權(quán)重很低的網(wǎng)站上有大量抄襲、采集或者復(fù)制的內(nèi)容,很可能就不再爬行。
  • 第三步:預(yù)處理。搜索引擎將蜘蛛抓取回來(lái)的頁(yè)面,進(jìn)行各種步驟的預(yù)處理。? ?⒈提取文字,?⒉中文分詞, ⒊去停止詞, ⒋消除噪音(搜索引擎需要識(shí)別并消除這些噪聲,比如版權(quán)聲明文字、導(dǎo)航條、廣告等……), 5 正向索引,? 6 倒排索引, 7 鏈接關(guān)系計(jì)算, 8 特殊文件處理等。?除了HTML文件外,搜索引擎通常還能抓取和索引以文字為基礎(chǔ)的多種文件類(lèi)型,如 PDF、Word、WPS、XLS、PPT、TXT 文件等。我們?cè)谒阉鹘Y(jié)果中也經(jīng)常會(huì)看到這些文件類(lèi)型。但搜索引擎還不能處理圖片、視頻、Flash 這類(lèi)非文字內(nèi)容,也不能執(zhí)行腳本和程序。
  • 第四步:排名,提供檢索服務(wù)

但是,這些通用性搜索引擎也存在著一定的局限性,如:

  • (1) 不同領(lǐng)域、不同背景的用戶(hù)往往具有不同的檢索目的和需求,通用搜索引擎所返回的結(jié)果包含大量用戶(hù)不關(guān)心的網(wǎng)頁(yè)。
  • (2) 通用搜索引目標(biāo)是盡可能的網(wǎng)絡(luò)覆蓋率,有限的搜索引擎服務(wù)器資源與無(wú)限的網(wǎng)絡(luò)數(shù)據(jù)資源之間的矛盾將進(jìn)一步加深。
  • (3) 萬(wàn)維網(wǎng)數(shù)據(jù)形式的豐富和網(wǎng)絡(luò)技術(shù)的不斷發(fā)展,圖片、數(shù)據(jù)庫(kù)、音頻、視頻多媒體等不同數(shù)據(jù)大量出現(xiàn),通用搜索引擎往往對(duì)這些信息含量密集且具有一定結(jié)構(gòu)的數(shù)據(jù)無(wú)能為力,不能很好地發(fā)現(xiàn)和獲取。
  • (4) 通用搜索引擎大多提供基于關(guān)鍵字的檢索,難以支持根據(jù)語(yǔ)義信息提出的查詢(xún)。

為了解決上述問(wèn)題,定向抓取相關(guān)網(wǎng)頁(yè)資源的聚焦爬蟲(chóng)應(yīng)運(yùn)而生。 聚焦爬蟲(chóng)是一個(gè)自動(dòng)下載網(wǎng)頁(yè)的程序,它根據(jù)既定的抓取目標(biāo),有選擇的訪問(wèn)萬(wàn)維網(wǎng)上的網(wǎng)頁(yè)與相關(guān)的鏈接,獲取所需要的信息。

與通用爬蟲(chóng)(general purpose web crawler)不同,聚焦爬蟲(chóng)并不追求大的覆蓋,而將目標(biāo)定為抓取與某一特定主題內(nèi)容相關(guān)的網(wǎng)頁(yè),為面向主題的用戶(hù)查詢(xún)準(zhǔn)備數(shù)據(jù)資源。

聚焦爬蟲(chóng)工作原理以及關(guān)鍵技術(shù)概述:

網(wǎng)絡(luò)爬蟲(chóng)是一個(gè)自動(dòng)提取網(wǎng)頁(yè)的程序,它為搜索引擎從萬(wàn)維網(wǎng)上下載網(wǎng)頁(yè),是搜索引擎的重要組成。傳統(tǒng)爬蟲(chóng)從一個(gè)或若干初始網(wǎng)頁(yè)的URL開(kāi)始,獲得初始網(wǎng)頁(yè)上的URL,在抓取網(wǎng)頁(yè)的過(guò)程中,不斷從當(dāng)前頁(yè)面上抽取新的URL放入隊(duì)列,直到滿(mǎn)足系統(tǒng)的一定停止條件。聚焦爬蟲(chóng)的工作流程較為復(fù)雜,需要根據(jù)一定的網(wǎng)頁(yè)分析算法過(guò)濾與主題無(wú)關(guān)的鏈接,保留有用的鏈接并將其放入等待抓取的URL隊(duì)列。然后,它將根據(jù)一定的搜索策略從隊(duì)列中選擇下一步要抓取的網(wǎng)頁(yè)URL,并重復(fù)上述過(guò)程,直到達(dá)到系統(tǒng)的某一條件時(shí)停止。另外,所有被爬蟲(chóng)抓取的網(wǎng)頁(yè)將會(huì)被系統(tǒng)存貯,進(jìn)行一定的分析、過(guò)濾,并建立索引,以便之后的查詢(xún)和檢索;對(duì)于聚焦爬蟲(chóng)來(lái)說(shuō),這一過(guò)程所得到的分析結(jié)果還可能對(duì)以后的抓取過(guò)程給出反饋和指導(dǎo)。

相對(duì)于通用網(wǎng)絡(luò)爬蟲(chóng),聚焦爬蟲(chóng)還需要解決三個(gè)主要問(wèn)題:

  • (1) 對(duì)抓取目標(biāo)的描述或定義;
  • (2) 對(duì)網(wǎng)頁(yè)或數(shù)據(jù)的分析與過(guò)濾;
  • (3) 對(duì)URL的搜索策略。

抓取目標(biāo)的描述和定義是決定網(wǎng)頁(yè)分析算法與URL搜索策略如何制訂的基礎(chǔ)。而網(wǎng)頁(yè)分析算法和候選URL排序算法是決定搜索引擎所提供的服務(wù)形式和爬蟲(chóng)網(wǎng)頁(yè)抓取行為的關(guān)鍵所在。這兩個(gè)部分的算法又是緊密相關(guān)的。

網(wǎng)絡(luò)爬蟲(chóng)的發(fā)展趨勢(shì)

隨著 AJAX/Web2.0 的流行,如何抓取 AJAX 等動(dòng)態(tài)頁(yè)面成了搜索引擎急需解決的問(wèn)題,如果搜索引擎依舊采用“爬”的機(jī)制,是無(wú)法抓取到 AJAX 頁(yè)面的有效數(shù)據(jù)的。 對(duì)于 AJAX 這樣的技術(shù),所需要的爬蟲(chóng)引擎必須是基于驅(qū)動(dòng)的。而如果想要實(shí)現(xiàn)事件驅(qū)動(dòng),首先需要解決以下問(wèn)題:

  • 第一:JavaScript 的交互分析和解釋;
  • 第二:DOM 事件的處理和解釋分發(fā);
  • 第三:動(dòng)態(tài) DOM 內(nèi)容語(yǔ)義的抽取。

爬蟲(chóng)發(fā)展的幾個(gè)階段(博士論文copy)

  • 第一個(gè)階段:可以說(shuō)是 早期爬蟲(chóng),斯坦福的幾位同學(xué)完成的抓取,當(dāng)時(shí)的互聯(lián)網(wǎng)基本都是完全開(kāi)放的,人類(lèi)流量是主流;
  • 第二個(gè)階段:是?分布式爬蟲(chóng),但是爬蟲(chóng)面對(duì)新的問(wèn)題是數(shù)據(jù)量越來(lái)越大,傳統(tǒng)爬蟲(chóng)已經(jīng)解決不了把數(shù)據(jù)都抓全的問(wèn)題,需要更多的爬蟲(chóng),于是調(diào)度問(wèn)題就出現(xiàn)了;
  • 第三階段:是?Deep Web?爬蟲(chóng)。此時(shí)面對(duì)新的問(wèn)題是數(shù)據(jù)之間的link越來(lái)越少,比如淘寶,點(diǎn)評(píng)這類(lèi)數(shù)據(jù),彼此link很少,那么抓全這些數(shù)據(jù)就很難;還有一些數(shù)據(jù)是需要提交查詢(xún)?cè)~才能獲取,比如機(jī)票查詢(xún),那么需要尋找一些手段“發(fā)現(xiàn)”更多,更完整的不是明面上的數(shù)據(jù)。
  • 第四階段:智能爬蟲(chóng),這主要是爬蟲(chóng)又開(kāi)始面對(duì)新的問(wèn)題:社交網(wǎng)絡(luò)數(shù)據(jù)的抓取。

社交網(wǎng)絡(luò)對(duì)爬蟲(chóng)帶來(lái)的新的挑戰(zhàn)包括

  • 有一條賬號(hào)護(hù)城河。我們通常稱(chēng)UGC(User Generated Content)指用戶(hù)原創(chuàng)內(nèi)容。為 web2.0,即數(shù)據(jù)從單向傳達(dá),到雙向互動(dòng),人民群眾可以與網(wǎng)站產(chǎn)生交互,因此產(chǎn)生了賬號(hào),每個(gè)人都通過(guò)賬號(hào)來(lái)標(biāo)識(shí)身份,提交數(shù)據(jù),這樣一來(lái)社交網(wǎng)絡(luò)就可以通過(guò)封賬號(hào)來(lái)提高數(shù)據(jù)抓取的難度,通過(guò)賬號(hào)來(lái)發(fā)現(xiàn)非人類(lèi)流量。之前沒(méi)有賬號(hào)只能通過(guò)cookie和ip。cookie又是易變,易揮發(fā)的,很難長(zhǎng)期標(biāo)識(shí)一個(gè)用戶(hù)。
  • 網(wǎng)絡(luò)走向封閉。新浪微博在 2012 年以前都是基本不封的,隨便寫(xiě)一個(gè)程序怎么抓都不封,但是很快,越來(lái)越多的站點(diǎn)都開(kāi)始防止競(jìng)爭(zhēng)對(duì)手,防止爬蟲(chóng)來(lái)抓取,數(shù)據(jù)逐漸走向封閉,越來(lái)越多的人難以獲得數(shù)據(jù)。甚至都出現(xiàn)了專(zhuān)業(yè)的爬蟲(chóng)公司,這在2010年以前是不可想象的。。
  • 反爬手段,封殺手法千差萬(wàn)別。寫(xiě)一個(gè)通用的框架抓取成百上千萬(wàn)的網(wǎng)站已經(jīng)成為歷史,或者說(shuō)已經(jīng)是一個(gè)技術(shù)相對(duì)成熟的工作,也就是已經(jīng)有相對(duì)成熟的框架來(lái)”盜“成百上千的墓,但是極個(gè)別的墓則需要特殊手段了,目前市場(chǎng)上比較難以抓取的數(shù)據(jù)包括,微信公共賬號(hào),微博,facebook,ins,淘寶等等。具體原因各異,但基本無(wú)法用一個(gè)統(tǒng)一框架來(lái)完成,太特殊了。如果有一個(gè)通用的框架能解決我說(shuō)的這幾個(gè)網(wǎng)站的抓取,這一定是一個(gè)非常震撼的產(chǎn)品,如果有,一定要告訴我,那我公開(kāi)出來(lái),然后就改行了。

當(dāng)面對(duì)以上三個(gè)挑戰(zhàn)的時(shí)候,就需要智能爬蟲(chóng)。智能爬蟲(chóng)是讓爬蟲(chóng)的行為盡可能模仿人類(lèi)行為,讓反爬策略失效,只有”混在老百姓隊(duì)伍里面,才是安全的“,因此這就需要琢磨瀏覽器了,很多人把爬蟲(chóng)寫(xiě)在了瀏覽器插件里面,把爬蟲(chóng)寫(xiě)在了手機(jī)里面,寫(xiě)在了路由器里面(春節(jié)搶票王)。再有一個(gè)傳統(tǒng)的爬蟲(chóng)都是只有讀操作的,沒(méi)有寫(xiě)操作,這個(gè)很容易被判是爬蟲(chóng),智能的爬蟲(chóng)需要有一些自動(dòng)化交互的行為,這都是一些抵御反爬策略的方法。

1.3 爬蟲(chóng)基本原理

爬蟲(chóng)是模擬用戶(hù)在瀏覽器或者某個(gè)應(yīng)用上的操作,把操作的過(guò)程、實(shí)現(xiàn)自動(dòng)化的程序,當(dāng)我們?cè)跒g覽器中輸入一個(gè) url 后回車(chē),后臺(tái)會(huì)發(fā)生什么?比如說(shuō)你輸入http://www.sina.com.cn/,簡(jiǎn)單來(lái)說(shuō)這段過(guò)程發(fā)生了以下四個(gè)步驟:

  • 1. 查找域名對(duì)應(yīng)的IP地址。
  • 2. 向IP對(duì)應(yīng)的服務(wù)器發(fā)送請(qǐng)求。
  • 3. 服務(wù)器響應(yīng)請(qǐng)求,發(fā)回網(wǎng)頁(yè)內(nèi)容。
  • 4. 瀏覽器解析網(wǎng)頁(yè)內(nèi)容。

網(wǎng)絡(luò)爬蟲(chóng)本質(zhì):本質(zhì)就是瀏覽器http請(qǐng)求。瀏覽器和網(wǎng)絡(luò)爬蟲(chóng)是兩種不同的網(wǎng)絡(luò)客戶(hù)端,都以相同的方式來(lái)獲取網(wǎng)頁(yè)。

網(wǎng)絡(luò)爬蟲(chóng)要做的,簡(jiǎn)單來(lái)說(shuō),就是實(shí)現(xiàn)瀏覽器的功能。通過(guò)指定url,直接返回給用戶(hù)所需要的數(shù)據(jù), 而不需要一步步人工去操縱瀏覽器獲取。

瀏覽器是如何發(fā)送和接收這個(gè)數(shù)據(jù)呢?

  • HTTP 簡(jiǎn)介:HTTP協(xié)議(HyperText Transfer Protocol,超文本傳輸協(xié)議)目的是為了提供一種發(fā)布和接收HTML(HyperText Markup Language)頁(yè)面的方法。
  • HTTP 協(xié)議所在的協(xié)議層(了解):HTTP 是基于TCP協(xié)議之上的。在 TCP/IP 協(xié)議參考模型的各層對(duì)應(yīng)的協(xié)議如下圖,其中HTTP是應(yīng)用層的協(xié)議。 默認(rèn)HTTP的端口號(hào)為80,HTTPS的端口號(hào)為443。

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 網(wǎng)絡(luò)模型圖

HTTP 工作過(guò)程

一次 HTTP 操作稱(chēng)為一個(gè)事務(wù),其工作整個(gè)過(guò)程如下:

  • 1 ) 、地址解析。如用客戶(hù)端瀏覽器請(qǐng)求這個(gè)頁(yè)面:http://localhost.com:8080/index.htm從中分解出協(xié)議名、主機(jī)名、端口、對(duì)象路徑等部分,對(duì)于我們的這個(gè)地址,解析得到的結(jié)果如下: 協(xié)議名:http 主機(jī)名:localhost.com 端口:8080 對(duì)象路徑:/index.htm在這一步,需要域名系統(tǒng)DNS解析域名localhost.com,得主機(jī)的IP地址。
  • 2)、封裝 HTTP 請(qǐng)求數(shù)據(jù)包。把以上部分結(jié)合本機(jī)自己的信息,封裝成一個(gè)HTTP請(qǐng)求數(shù)據(jù)包
  • 3)封裝成 TCP 包,建立TCP連接(TCP的三次握手)。在HTTP工作開(kāi)始之前,客戶(hù)機(jī)(Web瀏覽器)首先要通過(guò)網(wǎng)絡(luò)與服務(wù)器建立連接,該連接是通過(guò)TCP來(lái)完成的,該協(xié)議與IP協(xié)議共同構(gòu)建Internet,即著名的TCP/IP協(xié)議族,因此Internet又被稱(chēng)作是TCP/IP網(wǎng)絡(luò)。HTTP是比TCP更高層次的應(yīng)用層協(xié)議,根據(jù)規(guī)則,只有低層協(xié)議建立之后才能,才能進(jìn)行更層協(xié)議的連接,因此,首先要建立TCP連接,一般TCP連接的端口號(hào)是80。這里是8080端口
  • 4)客戶(hù)機(jī)發(fā)送請(qǐng)求命令。建立連接后,客戶(hù)機(jī)發(fā)送一個(gè)請(qǐng)求給服務(wù)器,請(qǐng)求方式的格式為:統(tǒng)一資源標(biāo)識(shí)符(URL)、協(xié)議版本號(hào),后邊是MIME信息包括請(qǐng)求修飾符、客戶(hù)機(jī)信息和可內(nèi)容。
  • 5)服務(wù)器響應(yīng)。服務(wù)器接到請(qǐng)求后給予相應(yīng)的響應(yīng)信息,其格式為一個(gè)狀態(tài)行,包括信息的協(xié)議版本號(hào)、一個(gè)成功或錯(cuò)誤的代碼,后邊是 MIME 信息包括服務(wù)器信息、實(shí)體信息和可能的內(nèi)容。實(shí)體消息:服務(wù)器向?yàn)g覽器發(fā)送頭信息后,它會(huì)發(fā)送一個(gè)空白行來(lái)表示頭信息的發(fā)送到此為結(jié)束,接著,它就以Content-Type應(yīng)答頭信息所描述的格式發(fā)送用戶(hù)所請(qǐng)求的實(shí)際數(shù)據(jù)
  • 6)服務(wù)器關(guān)閉 TCP 連接。一般情況下,一旦 Web 服務(wù)器向?yàn)g覽器發(fā)送了請(qǐng)求數(shù)據(jù),它就要關(guān)閉 TCP 連接,然后如果瀏覽器或者服務(wù)器在其頭信息加入了這行代碼 Connection:keep-alive 。TCP連接在發(fā)送后將仍然保持打開(kāi)狀態(tài),于是,瀏覽器可以繼續(xù)通過(guò)相同的連接發(fā)送請(qǐng)求。保持連接節(jié)省了為每個(gè)請(qǐng)求建立新連接所需的時(shí)間,還節(jié)約了網(wǎng)絡(luò)帶寬。

HTTP 協(xié)議棧數(shù)據(jù)流

HTTPS。HTTPS(全稱(chēng):Hypertext Transfer Protocol over Secure Socket Layer),是以安全為目標(biāo)的HTTP通道,簡(jiǎn)單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎(chǔ)是SSL。其所用的端口號(hào)是443。

SSL:安全套接層,是netscape公司設(shè)計(jì)的主要用于web的安全傳輸協(xié)議。這種協(xié)議在WEB上獲得了廣泛的應(yīng)用。通過(guò)證書(shū)認(rèn)證來(lái)確保客戶(hù)端和網(wǎng)站服務(wù)器之間的通信數(shù)據(jù)是加密安全的。

有兩種基本的加解密算法類(lèi)型:

  • 1)對(duì)稱(chēng)加密(symmetrcic encryption):密鑰只有一個(gè),加密解密為同一個(gè)密碼,且加解密速度快,典型的對(duì)稱(chēng)加密算法有DES、AES,RC5,3DES等;對(duì)稱(chēng)加密主要問(wèn)題是共享秘鑰,除你的計(jì)算機(jī)(客戶(hù)端)知道另外一臺(tái)計(jì)算機(jī)(服務(wù)器)的私鑰秘鑰,否則無(wú)法對(duì)通信流進(jìn)行加密解密。解決這個(gè)問(wèn)題的方案非對(duì)稱(chēng)秘鑰。
  • 2)非對(duì)稱(chēng)加密:使用兩個(gè)秘鑰:公共秘鑰和私有秘鑰。私有秘鑰由一方密碼保存(一般是服務(wù)器保存),另一方任何人都可以獲得公共秘鑰。這種密鑰成對(duì)出現(xiàn)(且根據(jù)公鑰無(wú)法推知私鑰,根據(jù)私鑰也無(wú)法推知公鑰),加密解密使用不同密鑰(公鑰加密需要私鑰解密,私鑰加密需要公鑰解密),相對(duì)對(duì)稱(chēng)加密速度較慢,典型的非對(duì)稱(chēng)加密算法有RSA、DSA等。

https 通信的優(yōu)點(diǎn):

客戶(hù)端產(chǎn)生的密鑰只有客戶(hù)端和服務(wù)器端能得到;
加密的數(shù)據(jù)只有客戶(hù)端和服務(wù)器端才能得到明文;
客戶(hù)端到服務(wù)端的通信是安全的。

1.4 爬蟲(chóng)工作流程

網(wǎng)絡(luò)爬蟲(chóng)的基本工作流程如下:

  • 1. 首先選取一部分精心挑選的種子 URL;
  • 2. 將這些 URL 放入待抓取 URL 隊(duì)列;
  • 3. 從待抓取 URL 隊(duì)列中取出待抓取在 URL,解析 DNS,并且得到主機(jī)的 ip,將 URL 對(duì)應(yīng)的網(wǎng)頁(yè)下載下來(lái)并存儲(chǔ)到已下載網(wǎng)頁(yè)庫(kù)中。此外,將這些 URL 放進(jìn)已抓取 URL 隊(duì)列。
  • 4. 分析已抓取 URL 隊(duì)列中的 URL,分析其中的其他 URL,并且將 URL 放入待抓取 URL 隊(duì)列,從而進(jìn)入下一個(gè)循環(huán)。

?;ňW(wǎng) 爬取 示例:爬取 大學(xué)校花(?http://www.521609.com/daxuexiaohua/ )

這個(gè)爬蟲(chóng)只是爬取一個(gè) URL,并沒(méi)有提取更多 URL 進(jìn)行爬取

# -*- coding:utf-8 -*- import os import chardet import requests from bs4 import BeautifulSoupdef spider():url = "http://www.521609.com/daxuexiaohua/"proxies = {"http": "http://172.17.18.80:8080","https": "https://172.17.18.80:8080"}r = requests.get(url,# proxies=proxies)html = r.content.decode("gbk")soup = BeautifulSoup(html, "lxml")divs = soup.find_all("div", class_="index_img list_center")print(f'len(divs) : {len(divs)}')for div in divs:tag_ul = div.find('ul')tag_all_li = tag_ul.find_all('li')print(f'len(tag_all_li): {len(tag_all_li)}')for tag_li in tag_all_li:tag_img = tag_li.find('img')print(f'mm_name: {tag_img["alt"]}')print(f'\t\t mm_pic: http://www.521609.com{tag_img["src"]}')home_page = tag_li.find('a')print(f'\t\t home_page: http://www.521609.com{home_page["href"]}')# print(soup)if __name__ == "__main__":spider()# input('press any key to continue......')# pass

1.5 HTTP 代理神器 Fidder

Fiddler 不但能截獲各種瀏覽器發(fā)出的HTTP請(qǐng)求, 也可以截獲各種智能手機(jī)發(fā)出的 HTTP/HTTPS請(qǐng)求。 Fiddler 能捕獲 IOS 設(shè)備發(fā)出的請(qǐng)求,比如 IPhone, IPad, MacBook. 等等蘋(píng)果的設(shè)備。 同理,也可以截獲 Andriod,Windows Phone 的等設(shè)備發(fā)出的HTTP/HTTPS。工作原理:Fiddler 是以代理 web 服務(wù)器的形式工作的,它使用代理地址:127.0.0.1,端口:8888。

Fiddler 抓取 HTTPS 設(shè)置:啟動(dòng) Fiddler,打開(kāi)菜單欄中的 Tools > Fiddler Options,打開(kāi) “Fiddler Options” 對(duì)話(huà)框。

選中 Capture HTTPS CONNECTs,再選中下方 Ignore server certificate errors,

然后再點(diǎn)擊 Actions 安裝證書(shū)( 要抓取 HTTPS 的流量,必須安裝證書(shū) ),安裝為 "根證書(shū)"。。。

配置 Fiddler 允許遠(yuǎn)程連接( 可以抓取手機(jī)流量?):

?Connections 頁(yè)簽,選中 Allow remote computers to connect。重啟 Fidler(這一步很重要,必須做)。

Fiddler 如何捕獲 Chrome的會(huì)話(huà):switchyomega 安裝插件?

百度( 百度的時(shí)候把點(diǎn)去掉?):i點(diǎn)sha點(diǎn)dow點(diǎn)socks? 或者? lan點(diǎn)tern

打開(kāi)網(wǎng)址 chrome 網(wǎng)上應(yīng)用商店,然后搜索 "switchyomega"。

Fiddler 如何捕獲 Firefox 的會(huì)話(huà)
能支持 HTTP 代理的任意程序的數(shù)據(jù)包都能被 Fiddler 嗅探到,Fiddler 的運(yùn)行機(jī)制其實(shí)就是本機(jī)上監(jiān)聽(tīng) 8888 端口的 HTTP代理。 Fiddler2啟動(dòng)的時(shí)候默認(rèn)IE的代理設(shè)為了127.0.0.1:8888,而其他瀏覽器是需要手動(dòng)設(shè)置的,所以將Firefox的代理改為127.0.0.1:8888就可以監(jiān)聽(tīng)數(shù)據(jù)了。 Firefox 上通過(guò)如下步驟設(shè)置代理 點(diǎn)擊: Tools -> Options, 在Options 對(duì)話(huà)框上點(diǎn)擊Advanced tab - > network tab -> setting.

Fiddler 的基本界面

特別注意: 遇到這個(gè) Click 請(qǐng)點(diǎn)擊 Click?

Fiddler 強(qiáng)大的 Script 系統(tǒng)
Fiddler 包含了一個(gè)強(qiáng)大的基于事件腳本的子系統(tǒng),并且能使用 .net 語(yǔ)言進(jìn)行擴(kuò)展。?
官方的幫助文檔:?http://www.fiddler2.com/Fiddler/dev/ScriptSamples.asp

Fiddler 的?Fiddler Script 標(biāo)簽,如下圖:

在里面我們就可以編寫(xiě)腳本了, 看個(gè)實(shí)例讓所有 cnblogs 的會(huì)話(huà)都顯示紅色。 把這段腳本放在 OnBeforeRequest(oSession: Session) 方法下,并且點(diǎn)擊 "Save script"

if (oSession.HostnameIs("www.cnblogs.com")) {oSession["ui-color"] = "red"; }

這樣所有的cnblogs的會(huì)話(huà)都會(huì)顯示紅色。

1.6 HTTP 協(xié)議介紹

HTTP (HyperText Transfer Protocol) 提供了一種發(fā)布和接收HTML(HyperText Markup Language)頁(yè)面的方法。

Http 兩部分組成:請(qǐng)求、響應(yīng)。

客戶(hù)端請(qǐng)求消息:客戶(hù)端發(fā)送一個(gè)HTTP請(qǐng)求到服務(wù)器的請(qǐng)求消息包括以下格式:請(qǐng)求行(request line)、請(qǐng)求頭部(header)、空行和請(qǐng)求數(shù)據(jù)四個(gè)部分組成,下圖給出了請(qǐng)求報(bào)文的一般格式。

服務(wù)器響應(yīng)消息:HTTP 響應(yīng)也由四個(gè)部分組成,分別是:狀態(tài)行、消息報(bào)頭、空行響應(yīng)正文。

cookies 和 session

服務(wù)器客戶(hù)端 的交互僅限于請(qǐng)求/響應(yīng)過(guò)程,結(jié)束之后便斷開(kāi), 在下一次請(qǐng)求服務(wù)器會(huì)認(rèn)為新的客戶(hù)端。為了維護(hù)他們之間的鏈接,讓服務(wù)器知道這是前一個(gè)用戶(hù)發(fā)送的請(qǐng)求,必須在一個(gè)地方保存客戶(hù)端的信息:

  • Cookie 通過(guò)在客戶(hù)端記錄信息確定用戶(hù)身份。
  • Session 通過(guò)在服務(wù)器端記錄信息確定用戶(hù)身份。

HTTP 請(qǐng)求

請(qǐng)求方法

根據(jù) HTTP 標(biāo)準(zhǔn),HTTP 請(qǐng)求可以使用多種請(qǐng)求方法。
HTTP 1.0 定義了三種請(qǐng)求方法: GET,POST 和 HEAD方法。
HTTP 1.1 新增了五種請(qǐng)求方法:OPTIONS,PUT,DELETE,TRACE 和 CONNECT 方法。

序號(hào)

方法

描述

1

GET

請(qǐng)求指定的頁(yè)面信息,并返回實(shí)體主體。

2

HEAD

類(lèi)似于 get 請(qǐng)求,只不過(guò)返回的響應(yīng)中沒(méi)有具體的內(nèi)容,用于獲取報(bào)頭

3

POST

向指定資源提交數(shù)據(jù)進(jìn)行處理請(qǐng)求(例如提交表單或者上傳文件)。數(shù)據(jù)被包含在請(qǐng)求體中。

POST 請(qǐng)求可能會(huì)導(dǎo)致新的資源的建立和/或已有資源的修改。

4

PUT

從客戶(hù)端向服務(wù)器傳送的數(shù)據(jù)取代指定的文檔的內(nèi)容。

5

DELETE

請(qǐng)求服務(wù)器刪除指定的頁(yè)面。

6

CONNECT

HTTP/1.1 協(xié)議中預(yù)留給能夠?qū)⑦B接改為管道方式的代理服務(wù)器。

7

OPTIONS

允許客戶(hù)端查看服務(wù)器的性能。

8

TRACE

回顯服務(wù)器收到的請(qǐng)求,主要用于測(cè)試或診斷。

GET和POST方法區(qū)別歸納如下幾點(diǎn):

  • 1. GET 是從服務(wù)器上獲取數(shù)據(jù),POST 是向服務(wù)器傳送數(shù)據(jù)。
  • 2. GET 請(qǐng)求的時(shí)候,參數(shù)都顯示在瀏覽器網(wǎng)址上。POST 請(qǐng)求的時(shí)候,參數(shù)在請(qǐng)求體當(dāng)中,消息長(zhǎng)度沒(méi)有限制而且以隱式的方式進(jìn)行發(fā)送
  • 3. 盡量避免使用 Get 方式提交表單,因?yàn)橛锌赡軙?huì)導(dǎo)致安全問(wèn)題。 比如說(shuō)在登陸表單中用 Get 方式,用戶(hù)輸入的用戶(hù)名和密碼將在地址欄中暴露無(wú)遺。 但是在分頁(yè)程序中用 Get 方式就比用 Post 好。

URL概述

統(tǒng)一資源定位符(URL,英語(yǔ) Uniform / Universal Resource Locator的縮寫(xiě))是用于完整地描述 Internet 上網(wǎng)頁(yè)和其他資源的地址的一種標(biāo)識(shí)方法。

URL 格式:基本格式如下 schema://host[:port#]/path/…/[?query-string][#anchor]

  • 1. schema 協(xié)議 (例如:http, https, ftp)
  • 2. host 服務(wù)器的IP地址或者域名
  • 3. port# 服務(wù)器的端口(如果是走協(xié)議默認(rèn)端口,缺省端口80)
  • 4. path 訪問(wèn)資源的路徑
  • 5. query-string 參數(shù),發(fā)送給http服務(wù)器的數(shù)據(jù)
  • 6. anchor- 錨(跳轉(zhuǎn)到網(wǎng)頁(yè)的指定錨點(diǎn)位置)

例子:

  • http://www.sina.com.cn/
  • http://192.168.0.116:8080/index.jsp
  • http://item.jd.com/11052214.html#product-detail
  • http://www.website.com/test/test.aspx?name=sv&x=true#stuff
  • URL 和 URI 的區(qū)別

    • URL:統(tǒng)一資源定位符(uniform resource location);平時(shí)上網(wǎng)時(shí)在 IE 瀏覽器中輸入的那個(gè)地址就是 URL。比如:網(wǎng)易 http://www.163.com 就是一個(gè)URL 。URL 是 Internet上用來(lái)描述信息資源的字符串,主要用在各種 WWW 客戶(hù)程序和服務(wù)器程序上。采用 URL 可以用一種統(tǒng)一的格式來(lái)描述各種信息資源,包括文件、服務(wù)器的地址和目錄等。
    • URI:統(tǒng)一資源標(biāo)識(shí)符(uniform resource identifier)。Web 上可用的每種資源 - HTML 文檔、圖像、視頻片段、程序, 由一個(gè)通過(guò)通用資源標(biāo)志符 (Universal Resource Identifier, 簡(jiǎn)稱(chēng) "URI") 進(jìn)行定位。URI 是個(gè)純粹的語(yǔ)法結(jié)構(gòu),用于指定標(biāo)識(shí) web資源的字符串的各個(gè)不同部分,URL 是 URI 的一個(gè)特例,它包含定位 web 資源的足夠信息。
    • URL 是 URI 的一個(gè)子集

    一個(gè) URL 的請(qǐng)求過(guò)程:

    • 當(dāng)你在瀏覽器輸入U(xiǎn)RL?https://www.baidu.com/ 的時(shí)候,瀏覽器發(fā)送一個(gè)Request 去獲取?https://www.baidu.com/ 的 html。
    • 服務(wù)器把 Response 發(fā)送回給瀏覽器.
    • 瀏覽器分析 Response 中的 HTML,發(fā)現(xiàn)其中引用了很多其他文件,比如:圖片,CSS文件,JS文件。
    • 瀏覽器會(huì)自動(dòng)再次發(fā)送 Request 去獲取圖片,CSS文件,或者JS文件。
    • 當(dāng)所有的文件都下載成功后, 網(wǎng)頁(yè)就被顯示出來(lái)了。

    常用的請(qǐng)求報(bào)頭

    • Host:Host初始URL中的主機(jī)和端口,用于指定被請(qǐng)求資源的Internet主機(jī)和端口號(hào),它通常從HTTP URL中提取出來(lái)的
    • Connection:表示客戶(hù)端與服務(wù)連接類(lèi)型;
      1. client 發(fā)起一個(gè)包含 Connection:keep-alive 的請(qǐng)求
      2. server 收到請(qǐng)求后,如果 server 支持 keepalive 回復(fù)一個(gè)包含Connection:keep-alive的
      ? ?響應(yīng)不關(guān)閉連接,否則回復(fù)一個(gè)包含Connection:close的響應(yīng)關(guān)閉連接。
      3. 如果 client 收到包含 Connection:keep-alive 的響應(yīng),向同一個(gè)連接發(fā)送下一個(gè)請(qǐng)求,
      ? ?直到一方主動(dòng)關(guān)閉連接。 Keep-alive在很多情況下能夠重用連接,減少資源消耗,縮短響應(yīng)時(shí)間HTTP
    • Accept:表示瀏覽器支持的 MIME 類(lèi)型
      MIME 的英文全稱(chēng)是 Multipurpose Internet Mail Extensions(多用途互聯(lián)網(wǎng)郵件擴(kuò)展)
      eg:
      Accept:image/gif,表明客戶(hù)端希望接受GIF圖象格式的資源;
      Accept:text/html,表明客戶(hù)端希望接受html文本。
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      意思:瀏覽器支持的 MIME 類(lèi)型分別是 text/html、application/xhtml+xml、application/xml 和 */*,
      ? ? ? 優(yōu)先順序是它們從左到右的排列順序。
      Text:用于標(biāo)準(zhǔn)化地表示的文本信息,文本消息可以是多種字符集和或者多種格式的;
      Application:用于傳輸應(yīng)用程序數(shù)據(jù)或者二進(jìn)制數(shù)據(jù);設(shè)定某種擴(kuò)展名的文件用一種應(yīng)用程序來(lái)
      ? ? ? ? ? ? ?打開(kāi)的方式類(lèi)型,當(dāng)該擴(kuò)展名文件被訪問(wèn)的時(shí)候,瀏覽器會(huì)自動(dòng)使用指定應(yīng)用程序來(lái)打開(kāi)
      q 是權(quán)重系數(shù),范圍 0 =< q <= 1,q 值越大,請(qǐng)求越傾向于獲得其“;”之前的類(lèi)型表示的內(nèi)容,
      若沒(méi)有指定 q 值越大,請(qǐng)求越傾向于獲得其“,則默認(rèn)為1,
      若被賦值為0,則用于提醒服務(wù)器哪些是瀏覽器不接受的內(nèi)容類(lèi)型。

    Mime類(lèi)型

    擴(kuò)展名

    text/html

    .htm?.html *.shtml

    text/plain

    text/html是以html的形式輸出,比如<input type="text"/>就會(huì)在頁(yè)面上顯示一個(gè)文本框,而以plain形式就會(huì)在頁(yè)面上原樣顯示這段代碼

    application/xhtml+xml

    .xhtml?.xml

    text/css

    *.css

    application/msexcel

    .xls?.xla

    application/msword

    .doc?.dot

    application/octet-stream

    *.exe

    application/pdf

    *.pdf

    .....

    .....

    • Content-Type:POST 提交,application/x-www-form-urlencoded 提交的數(shù)據(jù)按照 key1=val1&key2=val2 的方式進(jìn)行編碼,key 和 val 都進(jìn)行了 URL 轉(zhuǎn)碼。
    • User-Agent: 瀏覽器類(lèi)型
    • Referer: 請(qǐng)求來(lái)自哪個(gè)頁(yè)面,用戶(hù)是從該 Referer URL頁(yè)面訪問(wèn)當(dāng)前請(qǐng)求的頁(yè)面。
    • Accept-Encoding:瀏覽器支持的壓縮編碼類(lèi)型,比如gzip,支持gzip的瀏覽器返回經(jīng)gzip編碼的HTML頁(yè)面。許多情形下這可以減少5到10倍的下載時(shí)間
      eg:
      Accept-Encoding:gzip;q=1.0, identity; q=0.5, *;q=0 // 按順序支持 gzip , identity
      如果有多個(gè)Encoding同時(shí)匹配, 按照q值順序排列
      如果請(qǐng)求消息中沒(méi)有設(shè)置這個(gè)域,服務(wù)器假定客戶(hù)端對(duì)各種內(nèi)容編碼都可以接受。
    • Accept-Language:瀏覽器所希望的語(yǔ)言種類(lèi),當(dāng)服務(wù)器能夠提供一種以上的語(yǔ)言版本時(shí)要用到。
      eg:
      Accept-Language:zh-cn
      如果請(qǐng)求消息中沒(méi)有設(shè)置這個(gè)報(bào)頭域,服務(wù)器假定客戶(hù)端對(duì)各種語(yǔ)言都可以接受。
    • Accept-Charset:瀏覽器可接受的字符集,用于指定客戶(hù)端接受的字符集
      eg:
      Accept-Charset:iso-8859-1,gb2312
      ISO8859-1,通常叫做Latin-1。Latin-1包括了書(shū)寫(xiě)所有西方歐洲語(yǔ)言不可缺少的附加字符;
      gb2312是標(biāo)準(zhǔn)中文字符集;
      UTF-8 是 UNICODE 的一種變長(zhǎng)字符編碼,可以解決多種語(yǔ)言文本顯示問(wèn)題,從而實(shí)現(xiàn)應(yīng)用國(guó)際化和本地化。
      如果在請(qǐng)求消息中沒(méi)有設(shè)置這個(gè)域,缺省是任何字符集都可以接受。

    HTTP 響應(yīng)

    服務(wù)器上每一個(gè)HTTP 應(yīng)答對(duì)象 response 都包含一個(gè)數(shù)字 "狀態(tài)碼"。HTTP 狀態(tài)碼表示 HTTP 協(xié)議所返回的響應(yīng)的狀態(tài)。

    比如:客戶(hù)端向服務(wù)器發(fā)送請(qǐng)求,如果成功地獲得請(qǐng)求的資源,則返回的狀態(tài)碼為200,表示響應(yīng)成功。如果請(qǐng)求的資源不存在, 則通常返回404錯(cuò)誤。

    HTTP?響應(yīng)狀態(tài)碼通常分為5種類(lèi)型,分別以1~5五個(gè)數(shù)字開(kāi)頭,由3位整數(shù)組成,第一個(gè)數(shù)字定義了響應(yīng)的類(lèi)別

    分類(lèi)

    分類(lèi)描述

    1**

    信息,服務(wù)器收到請(qǐng)求,需要請(qǐng)求者繼續(xù)執(zhí)行操作

    2**

    成功,操作被成功接收并處理

    3**

    重定向,需要進(jìn)一步的操作以完成請(qǐng)求

    4**

    客戶(hù)端錯(cuò)誤,請(qǐng)求包含語(yǔ)法錯(cuò)誤或無(wú)法完成請(qǐng)求

    5**

    服務(wù)器錯(cuò)誤,服務(wù)器在處理請(qǐng)求的過(guò)程中發(fā)生了錯(cuò)誤

    最常用的響應(yīng)狀態(tài)碼

    200 (OK): 請(qǐng)求成功,找到了該資源,并且一切正常。處理方式:獲得響應(yīng)的內(nèi)容,進(jìn)行處理?
    201 請(qǐng)求完成,結(jié)果是創(chuàng)建了新資源。新創(chuàng)建資源的URI可在響應(yīng)的實(shí)體中得到 ? ?處理方式:爬蟲(chóng)中不會(huì)遇到?
    202 請(qǐng)求被接受,但處理尚未完成 ? ?處理方式:阻塞等待?
    204 服務(wù)器端已經(jīng)實(shí)現(xiàn)了請(qǐng)求,但是沒(méi)有返回新的信 息。如果客戶(hù)是用戶(hù)代理,則無(wú)須為此更新自身的文檔視圖。 ? ?處理方式:丟棄
    300 該狀態(tài)碼不被HTTP/1.0的應(yīng)用程序直接使用, 只是作為3XX類(lèi)型回應(yīng)的默認(rèn)解釋。存在多個(gè)可用的被請(qǐng)求資源。 ? ?處理方式:若程序中能夠處理,則進(jìn)行進(jìn)一步處理,如果程序中不能處理,則丟棄
    301 (Moved Permanently): 請(qǐng)求的文檔在其他地方,新的URL在Location頭中給出,瀏覽器應(yīng)該自動(dòng)地訪問(wèn)新的URL。處理方式:重定向到分配的URL
    302 (Found): 類(lèi)似于301,但新的URL應(yīng)該被視為臨時(shí)性的替代,而不是永久性的。處理方式:重定向到臨時(shí)的URL?
    304 (NOT MODIFIED): 該資源在上次請(qǐng)求之后沒(méi)有任何修改。這通常用于瀏覽器的緩存機(jī)制。處理方式:丟棄?
    400 (Bad Request): 請(qǐng)求出現(xiàn)語(yǔ)法錯(cuò)誤。非法請(qǐng)求 ? ? 處理方式:丟棄?
    401 未授權(quán) ? ? 處理方式:丟棄?
    403 (FORBIDDEN): 客戶(hù)端未能獲得授權(quán)。這通常是在401之后輸入了不正確的用戶(hù)名或密碼。禁止訪問(wèn) ? ?處理方式:丟棄?
    404 (NOT FOUND): 在指定的位置不存在所申請(qǐng)的資源。沒(méi)有找到 。 ? ?處理方式:丟棄?
    5XX 回應(yīng)代碼以“5”開(kāi)頭的狀態(tài)碼表示服務(wù)器端發(fā)現(xiàn)自己出現(xiàn)錯(cuò)誤,不能繼續(xù)執(zhí)行請(qǐng)求 ? ?處理方式:丟棄
    500 (Internal Server Error): 服務(wù)器遇到了意料不到的情況,不能完成客戶(hù)的請(qǐng)求
    503 (Service Unavailable): 服務(wù)器由于維護(hù)或者負(fù)載過(guò)重未能應(yīng)答。
    例如,Servlet可能在數(shù)據(jù)庫(kù)連接池已滿(mǎn)的情況下返回503。服務(wù)器返回503時(shí)可以提供一個(gè)Retry-After頭

    常用的響應(yīng)報(bào)頭(了解)
    Location:表示客戶(hù)應(yīng)當(dāng)?shù)侥睦锶ヌ崛∥臋n,用于重定向接受者到一個(gè)新的位置
    Server:服務(wù)器名字,包含了服務(wù)器用來(lái)處理請(qǐng)求的軟件信息
    eg: Server響應(yīng)報(bào)頭域的一個(gè)例子:
    Server:Apache-Coyote/1.1
    Set-Cookie:設(shè)置和頁(yè)面關(guān)聯(lián)的Cookie。
    例如:前一個(gè) cookie 被存入瀏覽器并且瀏覽器試圖請(qǐng)求 http://www.ibm.com/foo/index.html 時(shí)
    Set-Cookie:customer=huangxp; path=/foo; domain=.ibm.com;?
    expires= Wednesday, 19-OCT-05 23:12:40 GMT;
    Set-Cookie的每個(gè)屬性解釋如下:
    Customer=huangxp 一個(gè)"名稱(chēng)=值"對(duì),把名稱(chēng)customer設(shè)置為值"huangxp",這個(gè)屬性在Cookie中必須有。
    path=/foo 服務(wù)器路徑。
    domain=.ibm.com 指定cookie 的域名。
    expires= Wednesday, 19-OCT-05 23:12:40 GMT 指定cookie 失效的時(shí)間

    POST 請(qǐng)求方式

    urllib 使用示例:

    # encoding:UTF-8 import urllib.requestdef get_data():url = "http://www.baidu.com"data = urllib.request.urlopen(url).read()z_data = data.decode('UTF-8')print(z_data)get_data()

    get 和 post 方法:

    import urllib.request import urllib.parse import urllib.error # url異常處理def get_method():# GET 方法keyword = "python"keyword = urllib.parse.quote(keyword) # 搜索中文的方法url = "http://www.baidu.com/s?wd=" + keywordreq = urllib.request.Request(url)data = urllib.request.urlopen(req).read()print(data.decode('utf-8', 'ignore')) # 轉(zhuǎn)為utf-8,如果出現(xiàn)異常,責(zé)忽略fh = open("./1.html", "wb")fh.write(data)fh.close()def post_method():# POST 方法keyword = "python"keyword = urllib.parse.quote(keyword)url = "http://www.baidu.com/s"my_data = urllib.parse.urlencode({"wd": "python"}).encode('utf-8')req = urllib.request.Request(url, my_data)data = urllib.request.urlopen(req).read().decode("utf-8")print(data)if __name__ == '__main__':get_method()post_method()'''在清求url請(qǐng)求時(shí)會(huì)發(fā)現(xiàn)存在異常情況,常用的請(qǐng)求異常類(lèi)是 HTTPError/URLError 兩種,HTTPError異常時(shí)URLError異常的子類(lèi),是帶異常狀態(tài)碼和異常原因的,而URLError異常類(lèi)是不帶狀態(tài)碼的,所以在使用中不用直接用URLError代替HTTPError異常,如果要代替,一定要判斷是否有狀態(tài)碼屬性URLError:1/連接不上遠(yuǎn)程服務(wù)器;2/url不存在;3/本地沒(méi)有網(wǎng)絡(luò);4/假如觸發(fā) http error所以通常用特殊處理來(lái)使用URLError來(lái)替代HTTPError異常'''try:urllib.request.urlopen("http://www.blog.csdn.net")except urllib.error.URLError as e:if hasattr(e, "code"):print("code:")print(e.code)if hasattr(e, "reason"):print("reason:")print(e.reason)finally:print("URLError ")pass

    抓取拉鉤招聘信息:https://www.lagou.com/jobs/list_爬蟲(chóng)

    # -*- coding: utf-8 -*-import string from urllib import request, parse# proxy_handler = request.ProxyHandler({"http": 'http://192.168.17.1:8888'}) # opener = request.build_opener(proxy_handler) # request.install_opener(opener)page_num = 1 output = open('lagou.json', 'w')for page in range(1, page_num + 1):form_data = {'first': 'true','pn': '1','kd': '爬蟲(chóng)'}# 注意:對(duì)于需要傳入的 data 數(shù)據(jù),需要進(jìn)行 urlencode 編碼。form_data = parse.urlencode(form_data).encode('utf-8')print(f'運(yùn)行到第 ({page}) 頁(yè)面')send_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ''(KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36','Accept': 'application/json, text/javascript, */*; q=0.01','X-Requested-With': 'XMLHttpRequest'}# url = 'http://www.lagou.com/jobs/positionAjax.json?px=new&needAddtionalResult=false'url = 'https://www.lagou.com/jobs/positionAjax.json?city=北京&needAddtionalResult=false'# Python3 出現(xiàn) 'ascii' codec can't encode characters問(wèn)題# https://www.cnblogs.com/wuxiangli/p/9957601.htmlurl = parse.quote(url, safe=string.printable)req = request.Request(url=url, headers=send_headers, data=form_data, method='POST')# req.add_header('X-Requested-With', 'XMLHttpRequest')# req.headers = send_headersresponse = request.urlopen(req)res_html = response.read().decode('utf-8')print(res_html)# output.write(res_html + '\n') output.close() print('-' * 4 + 'end' + '-' * 4)

    提出一個(gè)問(wèn)題,如果要采集的是 拉鉤招聘網(wǎng)站 北京>>朝陽(yáng)區(qū)>>望京 以這個(gè)網(wǎng)站為例,該如何理解這個(gè)url ?

    http://www.lagou.com/jobs/list_?px=default&city=%E5%8C%97%E4%BA%AC&district=%E6%9C%9D%E9%98%B3%E5%8C%BA&bizArea=%E6%9C%9B%E4%BA%AC#filterBox

    URL 編碼 / 解碼:http://tool.chinaz.com/tools/urlencode.aspx

    # -*- coding: utf-8 -*-from urllib import request, parsequery = {'city': '北京','district': '朝陽(yáng)區(qū)','bizArea': '望京' } print(parse.urlencode(query)) page = 3 values = {'first': 'false','pn': str(page),'kd': '后端開(kāi)發(fā)', } form_data = parse.urlencode(values) print(form_data)

    小結(jié)

    • Content-Length: 是指報(bào)頭Header以外的內(nèi)容長(zhǎng)度,指 表單數(shù)據(jù)長(zhǎng)度
    • X-Requested-With: XMLHttpRequest :表示Ajax異步請(qǐng)求
    • Content-Type: application/x-www-form-urlencoded :表示:提交的表單數(shù)據(jù) 會(huì)按照name/value 值對(duì) 形式進(jìn)行編碼。例如:name1=value1&name2=value2... 。name 和 value 都進(jìn)行了 URL 編碼(utf-8、gb2312)

    2. 爬蟲(chóng)入門(mén) 基礎(chǔ)篇

    數(shù)據(jù)格式

    描述

    設(shè)計(jì)目標(biāo)

    XML

    Extensible Markup Language (可擴(kuò)展標(biāo)記語(yǔ)言)

    被設(shè)計(jì)為傳輸和存儲(chǔ)數(shù)據(jù),其焦點(diǎn)是數(shù)據(jù)的內(nèi)容

    HTML

    HyperText Markup Language(超文本標(biāo)記語(yǔ)言)

    顯示數(shù)據(jù)以及如何更好顯示數(shù)據(jù)

    HTML DOM

    HTML Document Object Model(文檔對(duì)象模型)

    通過(guò) JavaScript,您可以重構(gòu)整個(gè)HTML文檔。您可以添加、移除、改變或重排頁(yè)面上的項(xiàng)目。要改變頁(yè)面的某個(gè)東西,JavaScript就需要對(duì)HTML文檔中所有元素進(jìn)行訪問(wèn)的入口。

    XML

    XML DOM 定義訪問(wèn)和操作 XML 文檔的標(biāo)準(zhǔn)方法。 DOM 將 XML 文檔作為一個(gè)樹(shù)形結(jié)構(gòu),而樹(shù)葉被定義為節(jié)點(diǎn)。

    XML 示例

    <?xml version="1.0" encoding="utf-8"?> <bookstore> <book category="cooking"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="children"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="web"> <title lang="en">XQuery Kick Start</title> <author>James McGovern</author> <author>Per Bothner</author> <author>Kurt Cagle</author> <author>James Linn</author> <author>Vaidyanathan Nagarajan</author> <year>2003</year> <price>49.99</price> </book> <book category="web" cover="paperback"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> </bookstore>

    HTML DOM 示例

    HTML DOM 定義了訪問(wèn)和操作 HTML 文檔的標(biāo)準(zhǔn)方法。 DOM 以樹(shù)結(jié)構(gòu)表達(dá) HTML 文檔。

    2.1 頁(yè)面解析之?dāng)?shù)據(jù)提取

    抓取網(wǎng)站或者某個(gè)應(yīng)用的數(shù)據(jù)一般分為兩部分,非結(jié)構(gòu)化的文本,或結(jié)構(gòu)化的文本。

    • 結(jié)構(gòu)化的數(shù)據(jù):JSON、XML
    • 非結(jié)構(gòu)化的數(shù)據(jù):HTML文本(包含JavaScript代碼)

    HTML文本(包含JavaScript代碼)是最常見(jiàn)的數(shù)據(jù)格式,理應(yīng)屬于結(jié)構(gòu)化的文本組織,但因?yàn)橐话阄覀冃枰年P(guān)鍵信息并非直接可以得到,需要進(jìn)行對(duì)HTML的解析查找,甚至一些字符串操作才能得到,所以還是歸類(lèi)于非結(jié)構(gòu)化的數(shù)據(jù)處理中。

    把網(wǎng)頁(yè)比作一個(gè)人,那么 HTML 便是他的骨架JS 便是他的肌肉CSS 便是它的衣服。常見(jiàn)解析方式如下:

    • XPath
    • CSS選擇器
    • 正則表達(dá)式

    一段文本,例如一篇文章,或者一句話(huà),我們的初衷是提取有效信息,所以如果是滯后處理,可以直接存儲(chǔ),如果是需要實(shí)時(shí)提取有用信息,常見(jiàn)的處理方式如下:

    • 分詞,根據(jù)抓取的網(wǎng)站類(lèi)型,使用不同詞庫(kù),進(jìn)行基本的分詞,然后變成詞頻統(tǒng)計(jì)
    • NLP 自然語(yǔ)言處理,進(jìn)行語(yǔ)義分析,用結(jié)果表示,例如正負(fù)面等。

    2.2 非結(jié)構(gòu)化數(shù)據(jù)之 XPath

    XPath 語(yǔ)言:XPath(XML Path Language)是 XML 路徑語(yǔ)言,它是一種用來(lái)定位 XML 文檔中某部分位置的語(yǔ)言。將 HTML 轉(zhuǎn)換成 XML 文檔之后,用 XPath 查找 HTML 節(jié)點(diǎn)或元素。比如:用 "/" 來(lái)作為上下層級(jí)間的分隔,第一個(gè) "/" 表示文檔的根節(jié)點(diǎn)(注意,不是指文檔最外層的 tag 節(jié)點(diǎn),而是指文檔本身),對(duì)于一個(gè) HTML 文件來(lái)說(shuō),最外層的節(jié)點(diǎn)應(yīng)該是 "/html" 。

    XPath開(kāi)發(fā)工具:開(kāi)源的 XPath 表達(dá)式編輯工具:XMLQuire(XML格式文件可用)、chrome 插件 XPath Helper

    firefox插件 XPath Checker

    XPath語(yǔ)法 (?XPath語(yǔ)法參考文檔:http://www.w3school.com.cn/xpath/index.asp )

    XPath 是一門(mén)在 XML 文檔中查找信息的語(yǔ)言。
    XPath 可用來(lái)在 XML 文檔中對(duì)元素和屬性進(jìn)行遍歷。

    <?xml version="1.0" encoding="ISO-8859-1"?> <bookstore> <book> <title lang="eng">Harry Potter</title> <price>29.99</price> </book> <book> <title lang="eng">Learning XML</title> <price>39.95</price> </book> </bookstore>

    選取節(jié)點(diǎn) XPath 使用路徑表達(dá)式在 XML 文檔中選取節(jié)點(diǎn)。節(jié)點(diǎn)是通過(guò)沿著路徑或者 step 來(lái)選取的。
    下面列出了最有用的路徑表達(dá)式:

    表達(dá)式

    描述

    /

    從根節(jié)點(diǎn)選取。

    nodename

    選取此節(jié)點(diǎn)的所有子節(jié)點(diǎn)。

    //

    從當(dāng)前節(jié)點(diǎn) 選擇?所有匹配文檔中的節(jié)點(diǎn)

    .

    選取當(dāng)前節(jié)點(diǎn)。

    ..

    選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。

    @

    選取屬性。

    在下面的表格中,我們已列出了一些路徑表達(dá)式以及表達(dá)式的結(jié)果:

    路徑表達(dá)式

    結(jié)果

    /bookstore

    選取根元素 bookstore。注釋:假如路徑起始于正斜杠( / ),則此路徑始終代表到某元素的絕對(duì)路徑!

    bookstore

    選取 bookstore 元素的所有子節(jié)點(diǎn)。默認(rèn)從根節(jié)點(diǎn)選取

    bookstore/book

    選取屬于 bookstore 的子元素的所有 book 元素。

    //book

    選取所有 book 子元素,而不管它們?cè)谖臋n中的位置。

    //book/./title

    選取所有 book 子元素,從當(dāng)前節(jié)點(diǎn)查找title節(jié)點(diǎn)

    //price/..

    選取所有 book 子元素,從當(dāng)前節(jié)點(diǎn)查找父節(jié)點(diǎn)

    bookstore//book

    選擇屬于 bookstore 元素的后代的所有 book 元素,而不管它們位于 bookstore 之下的什么位置。

    //@lang

    選取名為 lang 的所有屬性。

    謂語(yǔ)條件(Predicates)
    謂語(yǔ)用來(lái)查找某個(gè)特定的信息或者包含某個(gè)指定的值的節(jié)點(diǎn)。
    所謂"謂語(yǔ)條件",就是對(duì)路徑表達(dá)式的附加條件
    謂語(yǔ)是被嵌在方括號(hào)中,都寫(xiě)在方括號(hào)"[]"中,表示對(duì)節(jié)點(diǎn)進(jìn)行進(jìn)一步的篩選。
    在下面的表格中,我們列出了帶有謂語(yǔ)的一些路徑表達(dá)式,以及表達(dá)式的結(jié)果:

    路徑表達(dá)式

    結(jié)果

    /bookstore/book[1]

    選取屬于 bookstore 子元素的第一個(gè) book 元素。

    /bookstore/book[last()]

    選取屬于 bookstore 子元素的最后一個(gè) book 元素。

    /bookstore/book[last()-1]

    選取屬于 bookstore 子元素的倒數(shù)第二個(gè) book 元素。

    /bookstore/book[position()<3]

    選取最前面的兩個(gè)屬于 bookstore 元素的子元素的 book 元素。

    //title[@lang]

    選取所有擁有名為 lang 的屬性的 title 元素。

    //title[@lang=’eng’]

    選取所有 title 元素,且這些元素?fù)碛兄禐?eng 的 lang 屬性。

    //book[price]

    選取所有 book 元素,且被選中的book元素必須帶有price子元素

    /bookstore/book[price>35.00]

    選取 bookstore 元素的所有 book 元素,且其中的 price 元素的值須大于 35.00。

    /bookstore/book[price>35.00]/title

    選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大于 35.00

    選取未知節(jié)點(diǎn):XPath 通配符可用來(lái)選取未知的 XML 元素。

    通配符

    描述

    *

    匹配任何元素節(jié)點(diǎn)。

    @*

    匹配任何屬性節(jié)點(diǎn)。

    在下面的表格中,我們列出了一些路徑表達(dá)式,以及這些表達(dá)式的結(jié)果:

    路徑表達(dá)式

    結(jié)果

    /bookstore/*

    選取 bookstore 元素的所有子元素。

    //*

    選取文檔中的所有元素。

    //title[@*]

    選取所有帶有屬性的 title 元素。

    選取若干路徑: 通過(guò)在路徑表達(dá)式中使用“|”運(yùn)算符,您可以選取若干個(gè)路徑。
    在下面的表格中,我們列出了一些路徑表達(dá)式,以及這些表達(dá)式的結(jié)果:

    路徑表達(dá)式

    結(jié)果

    //book/title | //book/price

    選取 book 元素的所有 title 和 price 元素。

    //title | //price

    選取文檔中的所有 title 和 price 元素。

    /bookstore/book/title | //price

    選取屬于 bookstore 元素的 book 元素的所有 title 元素,以及文檔中所有的 price 元素。

    XPath 高級(jí)用法

    模糊查詢(xún) contains

    目前許多 web 框架,都是動(dòng)態(tài)生成界面的元素id,因此在每次操作相同界面時(shí),ID都是變化的,這樣為自動(dòng)化測(cè)試造成了一定的影響。

    <div class="eleWrapper" title="請(qǐng)輸入用戶(hù)名"> <input type="text" class="textfield" name="ID9sLJQnkQyLGLhYShhlJ6gPzHLgvhpKpLzp2Tyh4hyb1b4pnvzxFR!-166749344!1357374592067" id="nt1357374592068" /> </div>

    解決方法 使用 xpath 的匹配功能,//input[contains(@id,'nt')]

    測(cè)試使用的XML <Root> <Person ID="1001" > <Name lang="zh-cn" >張城斌</Name> <Email xmlns="www.quicklearn.cn" > cbcye@live.com </Email> <Blog>http://cbcye.cnblogs.com</Blog> </Person> <Person ID="1002" > <Name lang="en" >Gary Zhang</Name> <Email xmlns="www.quicklearn.cn" > GaryZhang@cbcye.com</Email> <Blog>http://www.quicklearn.cn</Blog> </Person> </Root>

    1.查詢(xún)所有Blog節(jié)點(diǎn)值中帶有 cn 字符串的Person節(jié)點(diǎn)。Xpath表達(dá)式:/Root//Person[contains(Blog,'cn')]
    2.查詢(xún)所有Blog節(jié)點(diǎn)值中帶有 cn 字符串并且屬性ID值中有01的Person節(jié)點(diǎn)。Xpath表達(dá)式:/Root//Person[contains(Blog,'cn') and contains(@ID,'01')]

    xpath 學(xué)習(xí)筆記

    1.依靠自己的屬性,文本定位//td[text()='Data Import']//div[contains(@class,'cux-rightArrowIcon-on')]//a[text()='馬上注冊(cè)']//input[@type='radio' and @value='1'] 多條件//span[@name='bruce'][text()='bruce1'][1] 多條件//span[@id='bruce1' or text()='bruce2'] 找出多個(gè)//span[text()='bruce1' and text()='bruce2'] 找出多個(gè) 2.依靠父節(jié)點(diǎn)定位//div[@class='x-grid-col-name x-grid-cell-inner']/div//div[@id='dynamicGridTestInstanceformclearuxformdiv']/div//div[@id='test']/input 3.依靠子節(jié)點(diǎn)定位//div[div[@id='navigation']]//div[div[@name='listType']]//div[p[@name='testname']] 4.混合型//div[div[@name='listType']]//img//td[a//font[contains(text(),'seleleium2從零開(kāi)始 視屏')]]//input[@type='checkbox'] 5.進(jìn)階部分//input[@id='123']/following-sibling::input 找下一個(gè)兄弟節(jié)點(diǎn)//input[@id='123']/preceding-sibling::span 上一個(gè)兄弟節(jié)點(diǎn)//input[starts-with(@id,'123')] 以什么開(kāi)頭//span[not(contains(text(),'xpath'))] 不包含xpath字段的span 6.索引//div/input[2]//div[@id='position']/span[3]//div[@id='position']/span[position()=3]//div[@id='position']/span[position()>3]//div[@id='position']/span[position()<3]//div[@id='position']/span[last()]//div[@id='position']/span[last()-1] 7.substring 截取判斷<div data-for="result" id="swfEveryCookieWrap"></div>//*[substring(@id,4,5)='Every']/@id 截取該屬性 定位3,取長(zhǎng)度5的字符 //*[substring(@id,4)='EveryCookieWrap'] 截取該屬性從定位3 到最后的字符 //*[substring-before(@id,'C')='swfEvery']/@id 屬性 'C'之前的字符匹配//*[substring-after(@id,'C')='ookieWrap']/@id 屬性'C之后的字符匹配 8.通配符*//span[@*='bruce']//*[@name='bruce'] 9.軸//div[span[text()='+++current node']]/parent::div 找父節(jié)點(diǎn)//div[span[text()='+++current node']]/ancestor::div 找祖先節(jié)點(diǎn) 10.孫子節(jié)點(diǎn)//div[span[text()='current note']]/descendant::div/span[text()='123']//div[span[text()='current note']]//div/span[text()='123'] 兩個(gè)表達(dá)的意思一樣 11.following pre https://www.baidu.com/s?wd=xpath&pn=10&oq=xpath&ie=utf-8&rsv_idx=1&rsv_pq=df0399f30003691c&rsv_t=7dccXo734hMJVeb6AVGfA3434tA9U%2FXQST0DrOW%2BM8GijQ8m5rVN2R4J3gU//span[@class="fk fk_cur"]/../following::a 往下的所有a//span[@class="fk fk_cur"]/../preceding::a[1] 往上的所有axpath提取多個(gè)標(biāo)簽下的text在寫(xiě)爬蟲(chóng)的時(shí)候,經(jīng)常會(huì)使用xpath進(jìn)行數(shù)據(jù)的提取,對(duì)于如下的代碼: <div id="test1">大家好!</div> 使用xpath提取是非常方便的。假設(shè)網(wǎng)頁(yè)的源代碼在selector中: data = selector.xpath('//div[@id="test1"]/text()').extract()[0] 就可以把“大家好!”提取到data變量中去。 然而如果遇到下面這段代碼呢? <div id="test2">美女,<font color=red>你的微信是多少?</font><div> 如果使用: data = selector.xpath('//div[@id="test2"]/text()').extract()[0] 只能提取到“美女,”; 如果使用: data = selector.xpath('//div[@id="test2"]/font/text()').extract()[0] 又只能提取到“你的微信是多少?” 可是我本意是想把“美女,你的微信是多少?”這一整個(gè)句子提取出來(lái)。 <div id="test3">我左青龍,<span id="tiger">右白虎,<ul>上朱雀,<li>下玄武。</li></ul>老牛在當(dāng)中,</span>龍頭在胸口。<div> 而且內(nèi)部的標(biāo)簽還不固定,如果我有一百段這樣類(lèi)似的html代碼,又如何使用xpath表達(dá)式,以最快最方便的方式提取出來(lái)? 使用xpath的string(.) 以第三段代碼為例: data = selector.xpath('//div[@id="test3"]') info = data.xpath('string(.)').extract()[0] 這樣,就可以把“我左青龍,右白虎,上朱雀,下玄武。老牛在當(dāng)中,龍頭在胸口”整個(gè)句子提取出來(lái),賦值給info變量。

    2.3 非結(jié)構(gòu)化數(shù)據(jù)之 lxml 庫(kù)

    lxml 是一種使用 Python 編寫(xiě)的庫(kù),可以迅速、靈活地處理 XML ,支持 XPath (XML Path Language),可以利用 XPath 語(yǔ)法快速的定位特定元素以及節(jié)點(diǎn)信息,提取出 HTML、XML 目標(biāo)數(shù)據(jù)

    lxml python 官方文檔?http://lxml.de/index.html

    簡(jiǎn)單使用

    首先利用 lxml 來(lái)解析 HTML 代碼,先來(lái)一個(gè)小例子來(lái)感受一下它的基本用法。使用 lxml 的 etree 庫(kù),然后利用 etree.HTML 初始化,然后我們將其打印出來(lái)。

    from lxml import etree text = ''' <div><ul><li class="item-0"><a href="link1.html">first item</a></li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></ul> </div> ''' # Parses an HTML document from a string html = etree.HTML(text) # Serialize an element to an encoded string representation of its XML tree result = etree.tostring(html) print(result)

    所以輸出結(jié)果如下,不僅補(bǔ)全了 li 標(biāo)簽,還添加了 body,html 標(biāo)簽。

    <html><body><div><ul><li class="item-0"><a href="link1.html">first item</a></li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul> </div> </body></html>

    XPath 實(shí)例測(cè)試

    (1)獲取所有的 <li> 標(biāo)簽

    from lxml import etree html_text = ''' <div><ul><li class="item-0"><a href="link1.html">first item</a></li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></ul> </div> ''' # Parses an HTML document from a string html = etree.HTML(text=html_text) # Serialize an element to an encoded string representation of its XML tree # result = etree.tostring(html) # print(result)print(type(html)) result = html.xpath('//li') print(result) print(len(result)) print(type(result)) print(type(result[0]))
    • 每個(gè)元素都是 Element 類(lèi)型;是一個(gè)個(gè)的標(biāo)簽元素,類(lèi)似現(xiàn)在的實(shí)例
      ? ? ? ? <Element li at 0x1014e0e18> Element類(lèi)型代表的就是
      ? ? ? ? <li class="item-0"><a href="link1.html">first item</a></li>

    [注意]:Element 類(lèi)型是一種靈活的容器對(duì)象,用于在內(nèi)存中存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)。每個(gè) element 對(duì)象都具有以下屬性:
      1. tag:string對(duì)象,標(biāo)簽,用于標(biāo)識(shí)該元素表示哪種數(shù)據(jù)(即元素類(lèi)型)。
      2. attrib:dictionary對(duì)象,表示附有的屬性。
      3. text:string對(duì)象,表示element的內(nèi)容。
      4. tail:string對(duì)象,表示element閉合之后的尾跡。

    (2)獲取 <li> 標(biāo)簽的所有 class

    html.xpath('//li/@class')# 運(yùn)行結(jié)果:['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']

    (3)獲取 <li> 標(biāo)簽下屬性 href 為 link1.html 的 <a> 標(biāo)簽

    html.xpath('//li/a[@href="link1.html"]')# 運(yùn)行結(jié)果:[<Element a at 0x10ffaae18>]

    (4)獲取 <li> 標(biāo)簽下的所有 <span> 標(biāo)簽

    注意這么寫(xiě)是不對(duì)的 html.xpath('//li/span') 因?yàn)?/ 是用來(lái)獲取子元素的,而 <span> 并不是 <li> 的子元素,所以,要用雙斜杠html.xpath('//li//span') # 運(yùn)行結(jié)果:[<Element span at 0x10d698e18>]

    (5)獲取 <li> 標(biāo)簽下的所有 class,不包括 <li>

    html.xpath('//li/a//@class') # 運(yùn)行結(jié)果:['blod']

    (6)獲取最后一個(gè) <li> 的<a> 的 href

    html.xpath('//li[last()]/a/@href') # 運(yùn)行結(jié)果:['link5.html']

    (7)獲取 class 為 bold 的標(biāo)簽

    result = html.xpath('//*[@class="bold"]') print result[0].tag # 運(yùn)行結(jié)果:span

    騰訊招聘:https://careers.tencent.com/search.html?pcid=40001

    2.4 非結(jié)構(gòu)化數(shù)據(jù)之 CSS Selector(CSS 選擇器)

    CSS 即層疊樣式表Cascading Stylesheet。?Selector 來(lái)定位(locate)頁(yè)面上的元素(Elements)。?Selenium 官網(wǎng)的Document 里極力推薦使用 CSS locator,而不是 XPath 來(lái)定位元素,原因是 CSS locator 比 XPath locator 速度快。

    Beautiful Soup

    安裝:https://pypi.org/project/bs4/

    官方文檔鏈接:?https://www.crummy.com/software/BeautifulSoup/bs4/doc/

    Beautiful Soup 是從 HTML 或 XML 文件中提取數(shù)據(jù),支持 Python 標(biāo)準(zhǔn)庫(kù)中的 HTML 解析器。還支持一些第三方的解析器,其中一個(gè)是 lxml。

    Beautiful Soup 自動(dòng)將輸入文檔轉(zhuǎn)換為 Unicode 編碼,輸出文檔轉(zhuǎn)換為 utf-8 編碼。你不需要考慮編碼方式,除非文檔沒(méi)有指定一個(gè)編碼方式,這時(shí),Beautiful Soup 就不能自動(dòng)識(shí)別編碼方式了。然后,你僅僅需要說(shuō)明一下原始編碼方式就可以了。另一個(gè)可供選擇的解析器是純 Python 實(shí)現(xiàn)的 html5lib , html5lib 的解析方式與瀏覽器相同,可以選擇下列方法來(lái)安裝 html5lib: pip install html5lib

    下表列出了主要的解析器:

    解析器

    使用方法

    優(yōu)勢(shì)

    劣勢(shì)

    Python標(biāo)準(zhǔn)庫(kù)

    BeautifulSoup(markup, "html.parser")

    Python的內(nèi)置標(biāo)準(zhǔn)庫(kù);執(zhí)行速度適中;文檔容錯(cuò)能力強(qiáng)

    Python 2.7.3 or 3.2.2前 的版本中文檔容錯(cuò)能力差

    lxml HTML 解析器

    BeautifulSoup(markup, "lxml")

    速度快;文檔容錯(cuò)能力強(qiáng) ;

    需要安裝C語(yǔ)言庫(kù)

    lxml XML 解析器

    BeautifulSoup(markup, ["lxml-xml"]) BeautifulSoup(markup, "xml")

    速度快;唯一支持XML的解析器

    需要安裝C語(yǔ)言庫(kù)

    html5lib

    BeautifulSoup(markup, "html5lib")

    最好的容錯(cuò)性;以瀏覽器的方式解析文檔;生成HTML5格式的文檔

    速度慢;不依賴(lài)外部擴(kuò)展

    推薦使用 lxml 作為解析器,因?yàn)樾矢摺?/strong>在 Python2.7.3 之前的版本和 Python3 中 3.2.2 之前的版本,必須安裝 lxml 或html5lib, 因?yàn)槟切?Python 版本的標(biāo)準(zhǔn)庫(kù)中內(nèi)置的 HTML 解析方法不夠穩(wěn)定.

    示例:使用 BeautifulSoup 解析這段代碼,能夠得到一個(gè) BeautifulSoup 的對(duì)象,并能按照標(biāo)準(zhǔn)的縮進(jìn)格式的結(jié)構(gòu)輸出:

    from bs4 import BeautifulSouphtml_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title"><b>The Dormouse's story</b></p><p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p><p class="story">...</p> """soup = BeautifulSoup(html_doc,'lxml')print(soup) # 打印 soup 對(duì)象的內(nèi)容

    打印 soup 對(duì)象的內(nèi)容

    格式化輸出soup 對(duì)象

    print(soup.prettify())

    CSS 選擇器

    在寫(xiě) CSS 時(shí):標(biāo)簽名不加任何修飾。類(lèi)名前加點(diǎn)。id名前加 “#”。?

    利用類(lèi)似的方法來(lái)篩選元素,用到的方法是 soup.select(),返回類(lèi)型是 list

    通過(guò)標(biāo)簽名查找

    from bs4 import BeautifulSouphtml_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title"><b>The Dormouse's story</b></p><p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p><p class="story">...</p> """soup = BeautifulSoup(html_doc, 'lxml')# print(soup) # 打印 soup 對(duì)象的內(nèi)容 print(soup.select('title')) # [<title>The Dormouse's story</title>] print(soup.select('a')) print(soup.select('b')) # [<b>The Dormouse's story</b>]

    通過(guò)類(lèi)名查找

    print(soup.select('.sister'))

    通過(guò) id 名查找

    print(soup.select('#link1')) #[<a class="sister" href="http://example.com/elsie" id="link1"></a>]

    直接子標(biāo)簽查找

    print(soup.select("head > title")) #[<title>The Dormouse's story</title>]

    組合查找:組合查找即標(biāo)簽名與類(lèi)名、id名進(jìn)行的組合原理是一樣的,例如查找 p 標(biāo)簽中,id 等于 link1的內(nèi)容,

    屬性 標(biāo)簽 不屬于 同一節(jié)點(diǎn) ?二者需要用 ?空格分開(kāi)

    print(soup.select('p #link1')) #[<a class="sister" href="http://example.com/elsie" id="link1"></a>]

    屬性查找

    查找時(shí)還可以加入屬性元素,屬性需要用中括號(hào)括起來(lái)

    注意:屬性和標(biāo)簽屬于同一節(jié)點(diǎn),所以中間不能加空格,否則會(huì)無(wú)法匹配到

    print(soup.select('a[class="sister"]'))print(soup.select('a[href="http://example.com/elsie"]')) #[<a class="sister" href="http://example.com/elsie" id="link1"></a>]

    同樣,屬性仍然可以與上述查找方式組合。不在同一節(jié)點(diǎn)的使用空格隔開(kāi),在同一節(jié)點(diǎn)的則不用加空格

    print soup.select('p a[href="http://example.com/elsie"]') #[<a class="sister" href="http://example.com/elsie" id="link1"></a>]

    以上的 select 方法返回的結(jié)果都是列表形式,可以遍歷形式輸出

    用 get_text() 方法來(lái)獲取它的內(nèi)容。

    print soup.select('title')[0].get_text() for title in soup.select('title'):print(title.get_text())

    Tag:Tag 是什么?通俗點(diǎn)講就是 HTML 中的一個(gè)個(gè)標(biāo)簽,例如:

    <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>print type(soup.select('a')[0])輸出:bs4.element.Tag

    對(duì)于 Tag,它有兩個(gè)重要的屬性,是 name 和 attrs,下面我們分別來(lái)感受一下

    1. name

    print(soup.name) print(soup.select('a')[0].name)輸出: [document] 'a'

    soup 對(duì)象本身比較特殊,它的 name 即為 [document],對(duì)于其他內(nèi)部標(biāo)簽,輸出的值便為標(biāo)簽本身的名稱(chēng)。

    2. attrs

    print(soup.select('a')[0].attrs)輸出: {'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'} 在這里,我們把 soup.select('a')[0] 標(biāo)簽的所有屬性打印輸出了出來(lái),得到的類(lèi)型是一個(gè)字典。 如果我們想要單獨(dú)獲取某個(gè)屬性,可以這樣,例如我們獲取它的 class 叫什么print soup.select('a')[0].attrs['class']輸出: ['sister']

    實(shí)戰(zhàn)案例:騰訊招聘網(wǎng)站:https://careers.tencent.com/search.html

    2.5 正則表達(dá)式

    掌握了 XPath、CSS選擇器,為什么還要學(xué)習(xí)正則?

    正則表達(dá)式,用標(biāo)準(zhǔn)正則解析,一般會(huì)把 HTML當(dāng) 做普通文本,用指定格式匹配當(dāng)相關(guān)文本,適合小片段文本,或者某一串字符(比如電話(huà)號(hào)碼、郵箱賬戶(hù)),或者HTML包含javascript的代碼,無(wú)法用CSS選擇器或者XPath

    在線正則表達(dá)式測(cè)試網(wǎng)站:https://tool.oschina.net/regex/

    Python 正則表達(dá)式 官方文檔:https://docs.python.org/zh-cn/3.8/library/re.html#regular-expression-objects

    正則表達(dá)式常見(jiàn)概念

    邊界匹配
    ^ -- 與字符串開(kāi)始的地方匹配,不匹配任何字符;
    $ -- 與字符串結(jié)束的地方匹配,不匹配任何字符;

    str = "cat abdcatdetf ios"^cat : 驗(yàn)證該行以c開(kāi)頭緊接著是a,然后是tios$ : 驗(yàn)證該行以t結(jié)尾倒數(shù)第二個(gè)字符為a倒數(shù)第三個(gè)字符為c^cat$: 以c開(kāi)頭接著是a->t然后是行結(jié)束:只有cat三個(gè)字母的數(shù)據(jù)行^$ : 開(kāi)頭之后馬上結(jié)束:空白行,不包括任何字符^ : 行的開(kāi)頭,可以匹配任何行,因?yàn)槊總€(gè)行都有行開(kāi)頭

    \b -- 匹配一個(gè)單詞邊界,也就是單詞和空格之間的位置,不匹配任何字符;

    "er\b"可以匹配"never"中的"er",但不能匹配"verb"中的"er"。

    \B -- \b取非,即匹配一個(gè)非單詞邊界;

    "er\B"能匹配"verb"中的"er",但不能匹配"never"中的"er"。

    數(shù)量詞的貪婪模式與非貪婪模式

    正則表達(dá)式通常用于在文本中查找匹配的字符串。Python里數(shù)量詞默認(rèn)是貪婪的(在少數(shù)語(yǔ)言里也可能是默認(rèn)非貪婪),總是嘗試匹配盡可能多的字符;非貪婪的則相反,總是嘗試匹配盡可能少的字符。例如:

    正則表達(dá)式"ab*"如果用于查找"abbbc",將找到"abbb"。而如果使用非貪婪的數(shù)量詞"ab*?",將找到"a"。

    反斜杠問(wèn)題

    與大多數(shù)編程語(yǔ)言相同,正則表達(dá)式里使用"\"作為轉(zhuǎn)義字符,這就可能造成反斜杠困擾。
    假如你需要匹配文本中的字符"\",那么使用編程語(yǔ)言表示的正則表達(dá)式里將需要4個(gè)反斜杠"\\\\":前兩個(gè)和后兩個(gè)分別用于在編程語(yǔ)言里轉(zhuǎn)義成反斜杠,轉(zhuǎn)換成兩個(gè)反斜杠后再在正則表達(dá)式里轉(zhuǎn)義成一個(gè)反斜杠。
    Python里的原生字符串很好地解決了這個(gè)問(wèn)題,這個(gè)例子中的正則表達(dá)式可以使用r"\\"表示。
    同樣,匹配一個(gè)數(shù)字的"\\d"可以寫(xiě)成r"\d"。有了原生字符串,你再也不用擔(dān)心是不是漏寫(xiě)了反斜杠,寫(xiě)出來(lái)的表達(dá)式也更直觀。

    import re a=re.search(r"\\","ab123bb\c") print a.group() \ a=re.search(r"\d","ab123bb\c") print a.group() 1

    Python Re模塊

    Python 自帶了 re 模塊,它提供了對(duì)正則表達(dá)式的支持。

    match 函數(shù):re.match 嘗試從字符串的起始位置匹配一個(gè)模式,如果不是起始位置匹配成功的話(huà),match() 就返回 none。
    下面是此函數(shù)的語(yǔ)法:re.match(pattern, string, flags=0)

    參數(shù)

    描述

    pattern

    這是正則表達(dá)式來(lái)進(jìn)行匹配。

    string

    這是字符串,這將被搜索匹配的模式,在字符串的開(kāi)頭。

    flags

    標(biāo)志位,用于控制正則表達(dá)式的匹配方式,如:是否區(qū)分大小寫(xiě),多行匹配等等。

    匹配成功則 re.match 方法返回一個(gè)匹配的對(duì)象,否則返回 None。

    我們可以使用group(num) 或 groups() 匹配對(duì)象函數(shù)來(lái)獲取匹配表達(dá)式。

    匹配對(duì)象的方法

    描述

    group(num=0)

    此方法返回整個(gè)匹配(或指定分組num)

    groups()

    此方法返回所有元組匹配的子組(空,如果沒(méi)有)

    示例代碼:

    #!/usr/bin/python import reline = "Cats are smarter than dogs"matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I)if matchObj:print("matchObj.group() : {0}".format(matchObj.group()))print("matchObj.group(1) : {0}".format(matchObj.group(1)))print(f"matchObj.group(2) : {matchObj.group(2)}") else:print("No match!!")''' 輸出: matchObj.group() : Cats are smarter than dogs matchObj.group(1) : Cats matchObj.group(2) : smarter '''

    正則表達(dá)式修飾符 - 選項(xiàng)標(biāo)志

    正則表達(dá)式字面可以包含一個(gè)可選的修飾符來(lái)控制匹配的各個(gè)方面。修飾符被指定為一個(gè)可選的標(biāo)志??梢允褂卯惢蛱峁┒鄠€(gè)修飾符(|),如先前所示,并且可以由這些中的一個(gè)來(lái)表示:

    修飾符

    描述

    re.I(re.IGNORECASE)

    使匹配對(duì)大小寫(xiě)不敏感

    re.M(MULTILINE)

    多行匹配,影響 ^ 和 $

    re.S(DOTALL)

    使 . 匹配包括換行在內(nèi)的所有字符

    re.X(VERBOSE)

    正則表達(dá)式可以是多行,忽略空白字符,并可以加入注釋

    findall() 函數(shù)
    re.findall(pattern, string, flags=0)

    返回字符串中所有模式的非重疊的匹配,作為字符串列表。該字符串掃描左到右,并匹配返回的順序發(fā)現(xiàn)

    默認(rèn):pattren = "\w+"target = "hello world\nWORLD HELLO"re.findall(pattren,target)['hello', 'world', 'WORLD', 'HELLO']re.I: re.findall("world", target,re.I)['world', 'WORLD']re.S: re.findall("world.WORLD", target,re.S)["world\nworld"]re.findall("hello.*WORLD", target,re.S)['hello world\nWORLD']re.M:re.findall("^WORLD",target,re.M)["WORLD"]re.X:reStr = '''\d{3} #區(qū)號(hào)-\d{8}''' #號(hào)碼re.findall(reStr,"010-12345678",re.X) ["010-12345678"]

    search 函數(shù)
    re.search 掃描整個(gè)字符串并返回第一個(gè)成功的匹配。
    下面是此函數(shù)語(yǔ)法:re.search(pattern, string, flags=0)

    參數(shù)

    描述

    pattern

    這是正則表達(dá)式來(lái)進(jìn)行匹配。

    string

    這是字符串,這將被搜索到的字符串中的任何位置匹配的模式。

    flags

    標(biāo)志位,用于控制正則表達(dá)式的匹配方式,如:是否區(qū)分大小寫(xiě),多行匹配等等。

    匹配成功則 re.search 方法返回一個(gè)匹配的對(duì)象,否則返回None。

    我們可以使用group(num) 或 groups() 匹配對(duì)象函數(shù)來(lái)獲取匹配表達(dá)式。

    #!/usr/bin/python import reline = "Cats are smarter than dogs"searchObj = re.search(r'(.*) are (.*?) .*', line, re.M | re.I)if searchObj:print("matchObj.group() : {0}".format(searchObj.group()))print("matchObj.group(1) : {0}".format(searchObj.group(1)))print(f"matchObj.group(2) : {searchObj.group(2)}") else:print("No match!!")''' 輸出: matchObj.group() : Cats are smarter than dogs matchObj.group(1) : Cats matchObj.group(2) : smarter '''

    re.match 與 re.search 的區(qū)別

    • re.match? 只匹配字符串的開(kāi)始,如果字符串開(kāi)始不符合正則表達(dá)式,則匹配失敗,函數(shù)返回None;
    • re.search 匹配整個(gè)字符串,直到找到一個(gè)匹配。

    示例代碼:

    #!/usr/bin/python import reline = "Cats are smarter than dogs";matchObj = re.match(r'dogs', line, re.M | re.I) if matchObj:print(f"match --> matchObj.group() : {matchObj.group()}") else:print("No match!!")searchObj = re.search(r'dogs', line, re.M | re.I) if searchObj:print(f"search --> searchObj.group() : {searchObj.group()}") else:print("Nothing found!!")''' No match!! search --> searchObj.group() : dogs '''

    搜索 和 替換

    Python 的 re 模塊提供了 re.sub 用于替換字符串中的匹配項(xiàng)。
    語(yǔ)法:re.sub(pattern, repl, string, max=0)
    返回的字符串是在字符串中用 RE 最左邊不重復(fù)的匹配來(lái)替換。如果模式?jīng)]有發(fā)現(xiàn),字符將被沒(méi)有改變地返回。 可選參數(shù) count 是模式匹配后替換的最大次數(shù);count 必須是非負(fù)整數(shù)。缺省值是 0 表示替換所有的匹配。

    實(shí)例:

    #!/usr/bin/python import reurl = "http://hr.tencent.com/position.php?&start=10" page = re.search(r'start=(\d+)', url).group(1)next_url = re.sub(r'start=(\d+)', 'start=' + str(int(page) + 10), url) print(f"Next Url : {next_url}")# 當(dāng)執(zhí)行上面的代碼,產(chǎn)生以下結(jié)果: # Next Url : http://hr.tencent.com/position.php?&start=20

    正則表達(dá)式語(yǔ)法

    2.6 頁(yè)面解析之結(jié)構(gòu)化數(shù)據(jù)

    結(jié)構(gòu)化的數(shù)據(jù)是最好處理,一般都是類(lèi)似 JSON 格式的字符串,直接解析 JSON 數(shù)據(jù),提取 JSON 的關(guān)鍵字段即可。

    JSON (JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式;適用于進(jìn)行數(shù)據(jù)交互的場(chǎng)景,比如網(wǎng)站前臺(tái)與后臺(tái)之間的數(shù)據(jù)交互。Python 自帶了 JSON 模塊,直接 import json 就可以使用了。Json 模塊提供了四個(gè)功能:dumps、dump、loads、load,用于字符串 和 python數(shù)據(jù)類(lèi)型間進(jìn)行轉(zhuǎn)換

    Python 操作 json 的標(biāo)準(zhǔn) api 庫(kù)參考:https://docs.python.org/zh-cn/3/library/json.html

    在線 JSON 格式化代碼:https://tool.oschina.net/codeformat/json

    1. json.loads()

    作用:json字符串 轉(zhuǎn)化 python 的類(lèi)型,返回一個(gè)python的類(lèi)型

    從 json 到 python 的類(lèi)型轉(zhuǎn)化對(duì)照如下:

    示例 :

    import jsona = "[1,2,3,4]" b = '{"k1":1,"k2":2}' # 當(dāng)字符串為字典時(shí){}外面必須是''單引號(hào){}里面必須是""雙引號(hào) print(json.loads(a)) # [1, 2, 3, 4]print(json.loads(b)) # {'k2': 2, 'k1': 1}

    豆瓣讀書(shū) 示例:

    import re import json import requestsdef crawl():custom_headers = {'Host': 'book.douban.com','Connection': 'keep-alive','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ''(KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;''q=0.8,application/signed-exchange;v=b3;q=0.9','Referer': 'https://book.douban.com/',}db_url = 'https://book.douban.com/subject/26393282/'r = requests.get(url=db_url, headers=custom_headers, verify=False)if 200 == r.status_code:html_text = r.textresult_list = re.findall(r'<script type="application/ld\+json">([\s\S]*?)</script>', html_text)if len(result_list):json_string = result_list[0]# print(json_string)json_dict = json.loads(json_string)# print(json.dumps(json_dict, ensure_ascii=False, indent=4))print(f'name: {json_dict["name"]}')print(f'author: {json_dict["author"][0]["name"]} {json_dict["author"][1]["name"]}')print(f'url: {json_dict["url"]}')print(f'isbn: {json_dict["isbn"]}')if __name__ == '__main__':crawl()pass

    2. json.dumps()
    實(shí)現(xiàn) python 類(lèi)型轉(zhuǎn)化為 json 字符串,返回一個(gè) str 對(duì)象
    從 python 原始類(lèi)型向 json 類(lèi)型的轉(zhuǎn)化對(duì)照如下:

    示例:

    import json a = [1,2,3,4] b ={"k1":1,"k2":2} c = (1,2,3,4)json.dumps(a) # '[1, 2, 3, 4]'json.dumps(b) # '{"k2": 2, "k1": 1}'json.dumps(c) # '[1, 2, 3, 4]'

    json.dumps 中的 ensure_ascii 參數(shù)引起的中文編碼問(wèn)題

    如果 Python Dict 字典含有中文,json.dumps 序列化時(shí)對(duì)中文默認(rèn)使用的 ascii 編碼

    import chardet import jsonb = {"name":"中國(guó)"}json.dumps(b) # '{"name": "\\u4e2d\\u56fd"}'print json.dumps(b) # {"name": "\u4e2d\u56fd"}chardet.detect(json.dumps(b)) # {'confidence': 1.0, 'encoding': 'ascii'}

    '中國(guó)' 中的 ascii 字符碼,而不是真正的中文。想輸出真正的中文需要指定 ensure_ascii=False

    json.dumps(b,ensure_ascii=False) # '{"name": "\xe6\x88\x91"}'print json.dumps(b,ensure_ascii=False) # {"name": "我"}chardet.detect(json.dumps(b,ensure_ascii=False)) # {'confidence': 0.7525, 'encoding': 'utf-8'}

    3. json.dump()

    把 Python 類(lèi)型 以 字符串的形式 寫(xiě)到文件中

    import json a = [1,2,3,4] json.dump(a,open("digital.json","w")) b = {"name":"我"} json.dump(b,open("name.json","w"),ensure_ascii=False) json.dump(b,open("name2.json","w"),ensure_ascii=True)

    4. json.load()

    讀取 文件中 json 形式的字符串元素 轉(zhuǎn)化成 python 類(lèi)型

    # -*- coding: utf-8 -*- import json number = json.load(open("digital.json")) print number b = json.load(open("name.json")) print b b.keys() print b['name']

    實(shí)戰(zhàn)項(xiàng)目:獲取 lagou 城市表信息

    import json import chardet import requestsurl = 'http://www.lagou.com/lbs/getAllCitySearchLabels.json?' custom_headers = {'Host': 'www.lagou.com','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ''(KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36',}response = requests.get(url, verify=False, headers=custom_headers)print(response.status_code) res_Html = response.text json_obj = json.loads(res_Html) print(type(json_obj)) print(json_obj)city_list =[]all_cities = json_obj['content']['data']['allCitySearchLabels']print(all_cities.keys())for key in all_cities:print(type(all_cities[key]))for item in all_cities[key]:name = item['name']print(f'name: {name}')city_list.append(name)fp = open('city.json', 'w') content = json.dumps(city_list, ensure_ascii=False) print(content) fp.write(content) fp.close()

    JSONPath

    • JSON 信息抽取類(lèi)庫(kù),從JSON文檔中抽取指定信息的工具
    • JSONPath 與 Xpath 區(qū)別:JsonPath 對(duì)于 JSON 來(lái)說(shuō),相當(dāng)于 XPATH 對(duì)于XML。

    下載地址:https://pypi.python.org/pypi/jsonpath/

    安裝方法:下載 jsonpath,解壓之后執(zhí)行 'python setup.py install '

    參考文檔

    XPath

    JSONPath

    Result

    /store/book/author

    $.store.book[*].author

    the authors of all books in the store

    //author

    $..author

    all authors

    /store/*

    $.store.*

    all things in store, which are some books and a red bicycle.

    /store//price

    $.store..price

    the price of everything in the store.

    //book[3]

    $..book[2]

    the third book

    //book[last()]

    $..book[(@.length-1)]$..book[-1:]

    the last book in order.

    //book[position()<3]

    $..book[0,1]$..book[:2]

    the first two books

    //book[isbn]

    $..book[?(@.isbn)]

    filter all books with isbn number

    //book[price<10]

    $..book[?(@.price<10)]

    filter all books cheapier than 10

    //*

    $..*

    all Elements in XML document. All members of JSON structure.

    案例

    還是以?http://www.lagou.com/lbs/getAllCitySearchLabels.json?為例,獲取所有城市

    import json import jsonpath import chardet import requestsurl = 'http://www.lagou.com/lbs/getAllCitySearchLabels.json?' custom_headers = {'Host': 'www.lagou.com','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ''(KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36',}response = requests.get(url, verify=False, headers=custom_headers)print(response.status_code) res_Html = response.text json_obj = json.loads(res_Html)city_list = jsonpath.jsonpath(json_obj, '$..name')print(city_list) print(type(city_list)) fp = open('city.json', 'w') content = json.dumps(city_list, ensure_ascii=False) print(content) fp.write(content) fp.close()

    XML

    xmltodict 模塊讓使用 XML 感覺(jué)跟操作 JSON 一樣
    Python 操作 XML 的第三方庫(kù)參考:https://github.com/martinblech/xmltodict
    模塊安裝:pip install xmltodict

    import json import xmltodictbook_dict = xmltodict.parse("""<bookstore><book><title lang="eng">Harry Potter</title><price>29.99</price></book><book><title lang="eng">Learning XML</title><price>39.95</price></book></bookstore>""")print(book_dict.keys()) print(json.dumps(book_dict, indent=4))

    數(shù)據(jù)提取總結(jié)

    • HTML、XML:XPath、CSS選擇器、正則表達(dá)式、轉(zhuǎn)化成 Python 類(lèi)型(xmltodict)
    • JSON:JSONPath,轉(zhuǎn)化成 Python 類(lèi)型進(jìn)行操作(json類(lèi))
    • 其他(js、文本、電話(huà)號(hào)碼、郵箱地址):正則表達(dá)式

    3. 爬蟲(chóng)實(shí)踐篇

    右鍵 ---> 查看源代碼F12? 區(qū)別:

    • 右鍵查看源代碼:實(shí)質(zhì)是一個(gè) Get 請(qǐng)求
    • F12 是整個(gè)頁(yè)面 所有的請(qǐng)求 url 加載完成的頁(yè)面

    3.1 案例 1:(?采集 百度貼吧 信息 )

    http://tieba.baidu.com/f?ie=utf-8&kw=%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB&fr=search

    解決問(wèn)題思路:

    • 1. 確認(rèn)需求數(shù)據(jù)在哪。右鍵查看源代碼
    • 2. Fidder 模擬發(fā)送數(shù)據(jù)

    代碼示例:https://cuiqingcai.com/993.html

    3.2 ?案例 2:(?惠州市網(wǎng)上掛牌交易系統(tǒng)? )

    為例:http://www.hdgtjy.com/index/Index4/? ?采集所有的掛牌交易信息

    import json import requestsdef crawl():url = 'http://www.hdgtjy.com/Index/PublicResults'custom_headers = {'X-Requested-With': 'XMLHttpRequest','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ''(KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36','Content-Type': 'application/x-www-form-urlencoded',}form_data = {'page': 1,'size': 500}r = requests.post(url=url, data=form_data, headers=custom_headers)if 200 == r.status_code:json_string = r.textjson_dict = json.loads(json_string)print(json.dumps(json_dict, ensure_ascii=False, indent=4))else:print(f'status_code:{r.status_code}')if __name__ == '__main__':crawl()pass

    3.3 案例 3:(?Requests 基本用法 與 藥品監(jiān)督管理局 )

    Requests

    優(yōu)點(diǎn):Requests 繼承了 urllib2 的所有特性。Requests 支持 HTTP 連接保持和連接池,支持使用 cookie 保持會(huì)話(huà),支持文件上傳,支持自動(dòng)確定響應(yīng)內(nèi)容的編碼,支持國(guó)際化的 URL 和 POST 數(shù)據(jù)自動(dòng)編碼。
    缺陷:requests 不是 python 自帶的庫(kù),需要另外安裝 easy_install or pip install。直接使用不能異步調(diào)用,速度慢(自動(dòng)確定響應(yīng)內(nèi)容的編碼)。pip install requests

    文檔:http://cn.python-requests.org/zh_CN/latest/index.html? ??http://www.python-requests.org/en/master/#

    使用方法:

    requests.get(url, data={'key1': 'value1'},headers={'User-agent','Mozilla/5.0'}) requests.post(url, data={'key1': 'value1'},headers={'content-type': 'application/json'})

    藥品監(jiān)督管理局 為例,采集 藥品 --->?國(guó)產(chǎn)藥品 下的所有的商品信息:http://app1.nmpa.gov.cn/data_nmpa/face3/base.jsp?tableId=25&tableName=TABLE25&title=國(guó)產(chǎn)藥品&bcId=152904713761213296322795806604

    # -*- coding: utf-8 -*- import urllib from lxml import etree import re import json import chardet import requestscurstart = 2values = {'tableId': '32','State': '1','bcId': '124356639813072873644420336632','State': '1','tableName': 'TABLE32','State': '1','viewtitleName': 'COLUMN302','State': '1','viewsubTitleName': 'COLUMN299,COLUMN303','State': '1','curstart': str(curstart),'State': '1','tableView': urllib.quote("國(guó)產(chǎn)藥品商品名"),'State': '1', }post_headers = {'Content-Type': 'application/x-www-form-urlencoded','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36' } url = "http://app1.sfda.gov.cn/datasearch/face3/search.jsp"response = requests.post(url, data=values, headers=post_headers)resHtml = response.text print response.status_code # print resHtmlUrls = re.findall(r'callbackC,\'(.*?)\',null', resHtml) for url in Urls:# 坑print url.encode('gb2312')

    查看運(yùn)行結(jié)果,感受一下。?

    總結(jié)

    1. User-Agent 偽裝 Chrome,欺騙 web 服務(wù)器
    2. urlencode 字典類(lèi)型 Dict、元祖 轉(zhuǎn)化成 url query 字符串

    1. 完成商品詳情頁(yè)采集
    2. 完成整個(gè)項(xiàng)目的采集

    詳情頁(yè)

    # -*- coding: utf-8 -*- from lxml import etree import re import json import requestsurl ='http://app1.sfda.gov.cn/datasearch/face3/content.jsp?tableId=32&tableName=TABLE32&tableView=%B9%FA%B2%FA%D2%A9%C6%B7%C9%CC%C6%B7%C3%FB&Id=211315' get_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36','Connection': 'keep-alive', } item = {} response = requests.get(url,headers=get_headers) resHtml = response.text print response.encoding html = etree.HTML(resHtml) for site in html.xpath('//tr')[1:]:if len(site.xpath('./td'))!=2:continuename = site.xpath('./td')[0].textif not name:continue# value =site.xpath('./td')[1].textvalue = re.sub('<.*?>', '', etree.tostring(site.xpath('./td')[1],encoding='utf-8'))item[name.encode('utf-8')] = valuejson.dump(item,open('sfda.json','w'),ensure_ascii=False)

    完整項(xiàng)目

    # -*- coding: utf-8 -*- import urllib from lxml import etree import re import json import requestsdef ParseDetail(url):# url = 'http://app1.sfda.gov.cn/datasearch/face3/content.jsp?tableId=32&tableName=TABLE32&tableView=%B9%FA%B2%FA%D2%A9%C6%B7%C9%CC%C6%B7%C3%FB&Id=211315'get_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36','Connection': 'keep-alive',}item = {}response = requests.get(url, headers=get_headers)resHtml = response.textprint response.encodinghtml = etree.HTML(resHtml)for site in html.xpath('//tr')[1:]:if len(site.xpath('./td')) != 2:continuename = site.xpath('./td')[0].textif not name:continue# value =site.xpath('./td')[1].textvalue = re.sub('<.*?>', '', etree.tostring(site.xpath('./td')[1], encoding='utf-8'))value = re.sub('', '', value)item[name.encode('utf-8').strip()] = value.strip()# json.dump(item, open('sfda.json', 'a'), ensure_ascii=False)fp = open('sfda.json', 'a')str = json.dumps(item, ensure_ascii=False)fp.write(str + '\n')fp.close()def main():curstart = 2values = {'tableId': '32','State': '1','bcId': '124356639813072873644420336632','State': '1','tableName': 'TABLE32','State': '1','viewtitleName': 'COLUMN302','State': '1','viewsubTitleName': 'COLUMN299,COLUMN303','State': '1','curstart': str(curstart),'State': '1','tableView': urllib.quote("國(guó)產(chǎn)藥品商品名"),'State': '1',}post_headers = {'Content-Type': 'application/x-www-form-urlencoded','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'}url = "http://app1.sfda.gov.cn/datasearch/face3/search.jsp"response = requests.post(url, data=values, headers=post_headers)resHtml = response.textprint response.status_code# print resHtmlUrls = re.findall(r'callbackC,\'(.*?)\',null', resHtml)for url in Urls:# 坑url = re.sub('tableView=.*?&', 'tableView=' + urllib.quote("國(guó)產(chǎn)藥品商品名") + "&", url)ParseDetail('http://app1.sfda.gov.cn/datasearch/face3/' + url.encode('gb2312'))if __name__ == '__main__':main()

    3.4 案例 4:(?拉鉤招聘網(wǎng) )

    以拉鉤具體詳情頁(yè)為例,進(jìn)行抓取。http://www.lagou.com/jobs/2101463.html

    from lxml import etree import requests import reresponse = requests.get('http://www.lagou.com/jobs/2101463.html') resHtml = response.texthtml = etree.HTML(resHtml)title = html.xpath('//h1[@title]')[0].attrib['title'] #salary= html.xpath('//span[@class="red"]')[0].textsalary = html.xpath('//dd[@class="job_request"]/p/span')[0].text worklocation = html.xpath('//dd[@class="job_request"]/p/span')[1].text experience = html.xpath('//dd[@class="job_request"]/p/span')[2].text education = html.xpath('//dd[@class="job_request"]/p/span')[3].text worktype = html.xpath('//dd[@class="job_request"]/p/span')[4].text Temptation = html.xpath('//dd[@class="job_request"]/p[2]')[0].textprint salary,worklocation,experience,education,worktype,Temptationdescription_tag = html.xpath('//dd[@class="job_bt"]')[0] description = etree.tostring( description_tag,encoding='utf-8') #print description deal_descp = re.sub('<.*?>','',description) print deal_descp.strip() publisher_name = html.xpath('//*[@class="publisher_name"]//@title')[0] pos = html.xpath('//*[@class="pos"]')[0].text chuli_lv = html.xpath('//*[@class="data"]')[0].text chuli_yongshi = html.xpath('//*[@class="data"]')[1].textprint chuli_lv,chuli_yongshi,pos,publisher_name

    3.5?案例 5:(?爬取糗事百科段子 )

    確定URL并抓取頁(yè)面代碼,首先我們確定好頁(yè)面的URL是 http://www.qiushibaike.com/8hr/page/4, 其中最后一個(gè)數(shù)字1代表頁(yè)數(shù),我們可以傳入不同的值來(lái)獲得某一頁(yè)的段子內(nèi)容。我們初步構(gòu)建如下的代碼來(lái)打印頁(yè)面代碼內(nèi)容試試看,先構(gòu)造最基本的頁(yè)面抓取方式,看看會(huì)不會(huì)成功。在Composer raw 模擬發(fā)送數(shù)據(jù)

    GET http://www.qiushibaike.com/8hr/page/2/ HTTP/1.1 Host: www.qiushibaike.com User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Accept-Language: zh-CN,zh;q=0.8

    在刪除了 User-Agent、Accept-Language 報(bào)錯(cuò)。應(yīng)該是 headers 驗(yàn)證的問(wèn)題,加上一個(gè) headers 驗(yàn)證試試看

    # -*- coding:utf-8 -*- import urllib import requests import re import chardet from lxml import etreepage = 2 url = 'http://www.qiushibaike.com/8hr/page/' + str(page) + "/" headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36','Accept-Language': 'zh-CN,zh;q=0.8'} try:response = requests.get(url, headers=headers)resHtml = response.texthtml = etree.HTML(resHtml)result = html.xpath('//div[contains(@id,"qiushi_tag")]')for site in result:#print etree.tostring(site,encoding='utf-8')item = {}imgUrl = site.xpath('./div/a/img/@src')[0].encode('utf-8')username = site.xpath('./div/a/@title')[0].encode('utf-8')#username = site.xpath('.//h2')[0].textcontent = site.xpath('.//div[@class="content"]')[0].text.strip().encode('utf-8')vote = site.xpath('.//i')[0].text#print site.xpath('.//*[@class="number"]')[0].textcomments = site.xpath('.//i')[1].textprint imgUrl, username, content, vote, commentsexcept Exception, e:print e

    多線程爬蟲(chóng) 實(shí)戰(zhàn):糗事百科

    python 下多線程的思考

    Queue 是 python 中的標(biāo)準(zhǔn)庫(kù),可以直接 import Queue 引用; 隊(duì)列是線程間最常用的交換數(shù)據(jù)的形式。對(duì)于共享資源,加鎖是個(gè)重要的環(huán)節(jié)。因?yàn)?python 原生的 list,dict 等,都是 not thread safe 的。而 Queue,是線程安全的,因此在滿(mǎn)足使用條件下,建議使用隊(duì)列。

    Python Queue 模塊有三種隊(duì)列及構(gòu)造函數(shù):

    1、Python Queue模塊的FIFO隊(duì)列先進(jìn)先出。 class Queue.Queue(maxsize) 2、LIFO類(lèi)似于堆,即先進(jìn)后出。 class Queue.LifoQueue(maxsize) 3、還有一種是優(yōu)先級(jí)隊(duì)列級(jí)別越低越先出來(lái)。 class Queue.PriorityQueue(maxsize)

    Queue(隊(duì)列對(duì)象)

    初始化: class Queue.Queue(maxsize) FIFO 先進(jìn)先出

    包中的常用方法:

    Queue.qsize() 返回隊(duì)列的大小 Queue.empty() 如果隊(duì)列為空,返回True,反之False Queue.full() 如果隊(duì)列滿(mǎn)了,返回True,反之False Queue.full 與 maxsize 大小對(duì)應(yīng) Queue.get([block[, timeout]])獲取隊(duì)列,timeout等待時(shí)間

    調(diào)用隊(duì)列對(duì)象的 get()方法從隊(duì)頭刪除并返回一個(gè)項(xiàng)目??蛇x參數(shù)為block,默認(rèn)為T(mén)rue。
    如果隊(duì)列為空且 block 為 True,get() 就使調(diào)用線程暫停,直至有項(xiàng)目可用。
    如果隊(duì)列為空且 block 為 False,隊(duì)列將引發(fā) Empty 異常。

    import Queue # 創(chuàng)建一個(gè)“隊(duì)列”對(duì)象 myqueue = Queue.Queue(maxsize = 10)# 將一個(gè)值放入隊(duì)列中 myqueue.put(10)# 將一個(gè)值從隊(duì)列中取出 myqueue.get()

    示例代碼:

    # -*- coding:utf-8 -*- import requests from lxml import etree from Queue import Queue import threading import time import jsonclass thread_crawl(threading.Thread):'''抓取線程類(lèi)'''def __init__(self, threadID, q):threading.Thread.__init__(self)self.threadID = threadIDself.q = qdef run(self):print "Starting " + self.threadIDself.qiushi_spider()print "Exiting ", self.threadIDdef qiushi_spider(self):# page = 1while True:if self.q.empty():breakelse:page = self.q.get()print 'qiushi_spider=', self.threadID, ',page=', str(page)url = 'http://www.qiushibaike.com/hot/page/' + str(page) + '/'headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36','Accept-Language': 'zh-CN,zh;q=0.8'}# 多次嘗試失敗結(jié)束、防止死循環(huán)timeout = 4while timeout > 0:timeout -= 1try:content = requests.get(url, headers=headers)data_queue.put(content.text)breakexcept Exception, e:print 'qiushi_spider', eif timeout < 0:print 'timeout', urlclass Thread_Parser(threading.Thread):'''頁(yè)面解析類(lèi);'''def __init__(self, threadID, queue, lock, f):threading.Thread.__init__(self)self.threadID = threadIDself.queue = queueself.lock = lockself.f = fdef run(self):print 'starting ', self.threadIDglobal total, exitFlag_Parserwhile not exitFlag_Parser:try:'''調(diào)用隊(duì)列對(duì)象的get()方法從隊(duì)頭刪除并返回一個(gè)項(xiàng)目??蛇x參數(shù)為block,默認(rèn)為T(mén)rue。如果隊(duì)列為空且block為T(mén)rue,get()就使調(diào)用線程暫停,直至有項(xiàng)目可用。如果隊(duì)列為空且block為False,隊(duì)列將引發(fā)Empty異常。'''item = self.queue.get(False)if not item:passself.parse_data(item)self.queue.task_done()print 'Thread_Parser=', self.threadID, ',total=', totalexcept:passprint 'Exiting ', self.threadIDdef parse_data(self, item):'''解析網(wǎng)頁(yè)函數(shù):param item: 網(wǎng)頁(yè)內(nèi)容:return:'''global totaltry:html = etree.HTML(item)result = html.xpath('//div[contains(@id,"qiushi_tag")]')for site in result:try:imgUrl = site.xpath('.//img/@src')[0]title = site.xpath('.//h2')[0].textcontent = site.xpath('.//div[@class="content"]')[0].text.strip()vote = Nonecomments = Nonetry:vote = site.xpath('.//i')[0].textcomments = site.xpath('.//i')[1].textexcept:passresult = {'imgUrl': imgUrl,'title': title,'content': content,'vote': vote,'comments': comments,}with self.lock:# print 'write %s' % json.dumps(result)self.f.write(json.dumps(result, ensure_ascii=False).encode('utf-8') + "\n")except Exception, e:print 'site in result', eexcept Exception, e:print 'parse_data', ewith self.lock:total += 1data_queue = Queue() exitFlag_Parser = False lock = threading.Lock() total = 0def main():output = open('qiushibaike.json', 'a')#初始化網(wǎng)頁(yè)頁(yè)碼page從1-10個(gè)頁(yè)面pageQueue = Queue(50)for page in range(1, 11):pageQueue.put(page)#初始化采集線程crawlthreads = []crawlList = ["crawl-1", "crawl-2", "crawl-3"]for threadID in crawlList:thread = thread_crawl(threadID, pageQueue)thread.start()crawlthreads.append(thread)#初始化解析線程parserListparserthreads = []parserList = ["parser-1", "parser-2", "parser-3"]#分別啟動(dòng)parserListfor threadID in parserList:thread = Thread_Parser(threadID, data_queue, lock, output)thread.start()parserthreads.append(thread)# 等待隊(duì)列清空while not pageQueue.empty():pass# 等待所有線程完成for t in crawlthreads:t.join()while not data_queue.empty():pass# 通知線程是時(shí)候退出global exitFlag_ParserexitFlag_Parser = Truefor t in parserthreads:t.join()print "Exiting Main Thread"with lock:output.close()if __name__ == '__main__':main()

    3.5 模擬登陸 及 驗(yàn)證碼

    使用表單登陸

    這種情況屬于 post 請(qǐng)求,即先向服務(wù)器發(fā)送表單數(shù)據(jù),服務(wù)器再將返回的 cookie 存入本地。

    data = {'data1':'XXXXX', 'data2':'XXXXX'}

    Requests:data 為 dict,json

    import requestsresponse = requests.post(url=url, data=data)

    使用 cookie 登陸

    使用 cookie 登陸,服務(wù)器會(huì)認(rèn)為你是一個(gè)已登陸的用戶(hù),所以就會(huì)返回給你一個(gè)已登陸的內(nèi)容。因此,需要驗(yàn)證碼的情況可以使用帶驗(yàn)證碼登陸的 cookie 解決。

    import requests requests_session = requests.session() response = requests_session.post(url=url_login, data=data)

    若存在驗(yàn)證碼,此時(shí)采用 response = requests_session.post(url=url_login, data=data)是不行的,做法應(yīng)該如下:

    response_captcha = requests_session.get(url=url_login, cookies=cookies) response1 = requests.get(url_login) # 未登陸 response2 = requests_session.get(url_login) # 已登陸,因?yàn)橹澳玫搅薘esponse Cookie! response3 = requests_session.get(url_results) # 已登陸,因?yàn)橹澳玫搅薘esponse Cookie!

    實(shí)戰(zhàn)項(xiàng)目:登錄豆瓣,并發(fā)表動(dòng)態(tài)

    模擬登陸的重點(diǎn),在于找到表單真實(shí)的提交地址,然后攜帶cookie,post數(shù)據(jù)即可,只要登陸成功,我們就可以訪問(wèn)其他任意網(wǎng)頁(yè),從而獲取網(wǎng)頁(yè)內(nèi)容。

    一個(gè)請(qǐng)求,只要正確模擬了method,url,header,body 這四要素,任何內(nèi)容都能抓下來(lái),而所有的四個(gè)要素,只要打開(kāi)瀏覽器-審查元素-Network就能看到!

    驗(yàn)證碼這一塊,現(xiàn)在主要是先把驗(yàn)證碼的圖片保存下來(lái),手動(dòng)輸入驗(yàn)證碼,后期可以研究下 python 自動(dòng)識(shí)別驗(yàn)證碼。

    但是驗(yàn)證碼保存成本地圖片,看的不不太清楚(有時(shí)間在改下),可以把驗(yàn)證碼的 url 地址在瀏覽器中打開(kāi),就可以看清楚驗(yàn)證碼了。

    主要實(shí)現(xiàn) 登錄豆瓣,并發(fā)表一句話(huà)

    # -*- coding:utf-8 -*-import re import requests from bs4 import BeautifulSoupclass DouBan(object):def __init__(self):self.__username = "豆瓣帳號(hào)" # 豆瓣帳號(hào)self.__password = "豆瓣密碼" # 豆瓣密碼self.__main_url = "https://www.douban.com"self.__login_url = "https://www.douban.com/accounts/login"self.__proxies = {"http": "http://172.17.18.80:8080","https": "https://172.17.18.80:8080"}self.__headers = {"Host": "www.douban.com","Origin": self.__main_url,"Referer": self.__main_url,"Upgrade-Insecure-Requests": "1","User-Agent": 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 ''(KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}self.__data = {"source": "index_nav","redir": "https://www.douban.com","form_email": self.__username,"form_password": self.__password,"login": u"登錄"}self.__session = requests.session()self.__session.headers = self.__headersself.__session.proxies = self.__proxiespassdef login(self):r = self.__session.post(self.__login_url, self.__data)if r.status_code == 200:html = r.textsoup = BeautifulSoup(html, "lxml")captcha_address = soup.find('img', id='captcha_image')['src']print(captcha_address) # 驗(yàn)證碼存在if captcha_address:# 利用正則表達(dá)式獲取captcha的IDre_captcha_id = r'<input type="hidden" name="captcha-id" value="(.*?)"/'captcha_id = re.findall(re_captcha_id, html)[0]print(captcha_id) # 保存到本地with open('captcha.jpg', 'w') as f:f.write(requests.get(captcha_address, proxies=self.__proxies).text)captcha = input('please input the captcha:')self.__data['captcha-solution'] = captchaself.__data['captcha-id'] = captcha_idr = self.__session.post(self.__login_url, data=self.__data)if r.status_code == 200:print("login success") data = {"ck": "NBJ2","comment": "模擬登錄"}r = self.__session.post(self.__main_url, data=data)print(r.status_code) else:print("登錄不需要驗(yàn)證碼") # 不需要驗(yàn)證碼的邏輯 和 上面輸入驗(yàn)證碼之后 的 邏輯 一樣# 此處代碼省略else:print("login fail", r.status_code) passif __name__ == "__main__":t = DouBan()t.login()pass

    運(yùn)行截圖:

    登錄豆瓣帳號(hào),可以看到說(shuō)了一句話(huà) “模擬登錄”

    Python 性能優(yōu)化

    因?yàn)?GIL 的存在,Python很難充分利用多核 CPU 的優(yōu)勢(shì)。

    但是,可以通過(guò)內(nèi)置的模塊 multiprocessing 實(shí)現(xiàn)下面幾種并行模式:

    • 1、 多進(jìn)程并行編程:對(duì)于CPU密集型的程序,可以使用multiprocessing的Process、Pool 等封裝好的類(lèi),通過(guò)多進(jìn)程的方式實(shí)現(xiàn)并行計(jì)算。但是因?yàn)檫M(jìn)程中的通信成本比較大,對(duì)于進(jìn)程之間需要大量數(shù)據(jù)交互的程序效率未必有大的提高。
    • 2、 多線程并行編程:對(duì)于IO密集型的程序,multiprocessing.dummy 模塊使用 multiprocessing 的接口封裝 threading,使得多線程編程也變得非常輕松(比如可以使用Pool的map接口,簡(jiǎn)潔高效)。
    • 3、分布式:multiprocessing 中的 Managers 類(lèi) 提供了可以在不同進(jìn)程之共享數(shù)據(jù)的方式,可以在此基礎(chǔ)上開(kāi)發(fā)出分布式的程序。 不同的業(yè)務(wù)場(chǎng)景可以選擇其中的一種或幾種的組合實(shí)現(xiàn)程序性能的優(yōu)化。

    總結(jié)

    以上是生活随笔為你收集整理的爬虫教程( 1 ) --- 初级、基础、实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    性色大片在线观看 | 亚洲成a人片77777潘金莲 | 高清免费av在线 | 久久99久久99精品免观看软件 | 日韩1页 | 国产裸体视频bbbbb | 一区二区三区观看 | 婷婷精品国产一区二区三区日韩 | 97精品国产97久久久久久免费 | 欧美一级乱黄 | 国产一卡在线 | 在线你懂的视频 | av片无限看| 欧美日韩国产伦理 | 日韩高清在线一区二区 | 日韩在线观看视频在线 | 日韩av免费一区二区 | 在线小视频 | 国精产品999国精产 久久久久 | 视频精品一区二区三区 | 国产在线观看 | 国产精品一区二区三区四 | 欧美 日韩 国产 中文字幕 | 欧美最猛性xxxxx亚洲精品 | 成人国产亚洲 | 欧美成人亚洲 | 天堂网一区 | 欧美少妇的秘密 | 日本aaaa级毛片在线看 | 久产久精国产品 | 午夜三级影院 | 毛片区 | 99精品毛片| 不卡中文字幕在线 | 一区二区三区手机在线观看 | 中文字幕资源网 国产 | 成人免费在线观看av | 亚洲成人家庭影院 | 成人网在线免费视频 | 久久av中文字幕片 | 欧美男女爱爱视频 | 黄色软件视频大全免费下载 | 国产一区免费视频 | 在线免费三级 | 久久手机免费观看 | 午夜精品一区二区三区免费 | 婷婷综合 | 99tvdz@gmail.com| 国产中文自拍 | 91热爆视频 | 最新日韩视频在线观看 | 91精选在线观看 | 免费观看成人网 | 久久精品久久精品久久39 | 国产精品久久久久久一区二区 | av免费在线网站 | 免费网站在线 | 九色91在线 | 五月天婷亚洲天综合网精品偷 | 91看片在线| 国产精品久久久久久久久久久久午 | 在线免费高清视频 | 免费视频一二三区 | 一区二区三区日韩视频在线观看 | 国产精品视频app | 午夜91在线| 永久免费的av电影 | 国内精品在线观看视频 | 在线观看mv的中文字幕网站 | 激情综合网色播五月 | 日韩视频区 | 九九九九热精品免费视频点播观看 | 成人欧美一区二区三区黑人麻豆 | 亚洲天天在线日亚洲洲精 | 免费日韩精品 | 国产精品久久久久久久久久尿 | 婷婷播播网 | 国产精品igao视频网网址 | 欧美91精品国产自产 | 亚洲精品天天 | 五月天久久婷婷 | 91av国产视频 | 国产网站在线免费观看 | 久久久久久久久久电影 | 国产91在线免费视频 | 精品国产伦一区二区三区 | 国产精品久久久久久久久蜜臀 | 中文在线www | 亚洲国产操 | 久久精品视频免费 | 人人插人人爱 | 激情婷婷 | 久久精品二区 | 玖玖爱免费视频 | 色婷婷综合视频在线观看 | 国产视频二 | 亚洲有 在线 | 亚洲资源视频 | 久久草草热国产精品直播 | 欧美激情另类 | 国产又粗又猛又黄又爽的视频 | 久久精品在线视频 | 欧美一级免费黄色片 | 久久精品中文字幕一区二区三区 | 最近中文字幕mv免费高清在线 | 69精品在线| www.人人干| 久久在线视频精品 | 欧美日本一二三 | 国产成人精品一区二区三区在线 | 激情小说久久 | 在线观看亚洲精品 | 国产精品黄色 | www激情久久 | 91久久在线观看 | 中文字幕 影院 | 91精品久久久久久综合乱菊 | 日韩亚洲在线观看 | 偷拍福利视频一区二区三区 | 午夜久久视频 | 欧美一级免费 | 91精品亚洲影视在线观看 | 人人爱爱人人 | 久久不射网站 | 婷婷色网址| 黄色特级一级片 | 国产视频资源 | 久久99精品国产91久久来源 | av中文字幕在线看 | 久久久久久免费网 | 成人国产精品 | 免费福利在线 | 免费网站在线观看成人 | 亚洲免费观看在线视频 | 色狠狠一区二区 | 国产欧美在线一区二区三区 | 很黄很污的视频网站 | 国产黄色成人av | 久草在线视频网站 | 99视频在线精品国自产拍免费观看 | 国产二区免费视频 | 精品无人国产偷自产在线 | 久久久久国产视频 | www.啪啪.com| 久久婷婷影视 | 激情综合色播五月 | 国产一二区免费视频 | 欧美黄色免费 | 日日草天天草 | 一级黄色片在线观看 | 日韩在线视频免费播放 | 国产美女精彩久久 | 国产你懂的在线 | 成人在线视频一区 | av在线电影播放 | 亚洲天堂视频在线 | 在线免费黄色 | 久久免费99精品久久久久久 | 国产一线二线三线性视频 | 91精品一区二区三区久久久久久 | 五月婷婷香蕉 | 精品国产电影一区二区 | 久久精品影片 | 亚洲va欧美va人人爽春色影视 | 婷婷丁香导航 | 欧美天天综合网 | 91久久丝袜国产露脸动漫 | 日韩高清精品免费观看 | 精产嫩模国品一二三区 | 久久久影院| 国产精品亚洲片夜色在线 | 日韩区欧美久久久无人区 | 国产精品刺激对白麻豆99 | av 一区 二区 久久 | 特级西西444www高清大视频 | 国产精品刺激对白麻豆99 | 久草精品视频在线观看 | 99久久毛片 | 亚洲精品大全 | 成人黄色毛片视频 | 伊人电影天堂 | 91高清完整版在线观看 | 亚洲网站在线 | 草免费视频 | 日韩一级黄色片 | 99综合久久| 综合网av| 在线播放av网址 | 午夜黄色一级片 | 国产一区二区久久久久 | 在线黄色毛片 | 婷婷国产v亚洲v欧美久久 | 国产精品99久久免费观看 | 亚洲成人av片在线观看 | 四虎精品成人免费网站 | 色中色综合 | 99热精品国产 | 亚洲成人av一区 | 日韩三级中文字幕 | 国产一级二级在线播放 | 草久视频在线 | 天天做天天爱天天爽综合网 | 日日日干| 激情久久综合 | 亚洲午夜久久久综合37日本 | av一区二区三区在线播放 | 亚洲成年人在线播放 | 国产精品一区二区三区观看 | 亚洲国产成人高清精品 | 亚洲综合在线观看视频 | 国产免费成人 | 一区二区三区久久 | 色婷婷综合久久久久中文字幕1 | 国产伦精品一区二区三区照片91 | 夜夜干天天操 | www.97视频 | 成年人毛片在线观看 | 亚洲一区二区三区四区精品 | 久久综合久久伊人 | 91看片成人 | 亚洲天堂精品 | 亚洲国产成人高清精品 | 91高清免费在线观看 | 深爱五月激情网 | 色就色,综合激情 | 国产精品久久久久久久妇 | 久草在线官网 | 中文乱码视频在线观看 | 天堂中文在线视频 | av资源网在线播放 | 91在线视频免费 | 久99久精品视频免费观看 | 91丨九色丨蝌蚪丨老版 | 亚洲v欧美v国产v在线观看 | 一区二区三区在线免费观看视频 | 丁香五月亚洲综合在线 | 久久久综合九色合综国产精品 | 五月婷在线播放 | 99热国内精品 | 麻豆视频免费网站 | 亚洲精品高清一区二区三区四区 | 久久久久久久久久久成人 | 91麻豆精品国产自产 | 激情五月色播五月 | 国产成人高清 | 欧美成人xxxx | www.色爱 | 99视频| 在线观看av大片 | 欧美精品久久久久久久久久久 | 国产91精品一区二区 | 永久免费精品视频 | 免费观看黄| 一级做a视频 | 日韩欧美一区二区三区在线观看 | 香蕉视频久久久 | 五月婷婷在线观看视频 | 精品久久精品久久 | 精品一区91 | 日韩电影一区二区在线 | 99热只有精品在线观看 | 九九久久久久久久久激情 | 国产精品一区二区免费视频 | 超碰在线97国产 | 综合网成人 | 国产精品av电影 | 欧美极品在线播放 | 亚洲综合色丁香婷婷六月图片 | 中文字幕在线播出 | 精品免费久久久久 | 亚洲成av人片一区二区梦乃 | 久久超| 成人a免费视频 | 水蜜桃亚洲一二三四在线 | 国产精品午夜8888 | 在线观看av麻豆 | 久久午夜免费视频 | 欧美一区二区三区在线视频观看 | 久久精品一区二区三区中文字幕 | 久久公开免费视频 | 男女激情片在线观看 | 又黄又刺激 | 亚洲欧美色婷婷 | 91精品办公室少妇高潮对白 | 国产一区高清在线 | 97视频在线免费 | 国产精品毛片一区二区在线 | 国语对白少妇爽91 | 日韩免费看片 | 久草在线免费在线观看 | 天天人人综合 | 8x成人在线 | 午夜视频在线观看一区二区三区 | 奇米影视8888 | 激情网在线视频 | 日本一区二区三区免费观看 | 麻豆国产在线播放 | 亚洲日本在线一区 | 精品国产乱码久久久久久浪潮 | 免费在线播放黄色 | 99久久99久国产黄毛片 | 欧美十八 | 国产成人精品电影久久久 | 五月天精品视频 | 91丨九色丨蝌蚪丨对白 | 国产日产在线观看 | 久草在线免费在线观看 | 亚洲精品一区二区三区新线路 | 久久a免费视频 | 色吊丝在线永久观看最新版本 | 色婷婷电影| adc在线观看 | 欧美成人在线免费 | 国产成人久久久77777 | 97超碰人人在线 | 99视频免费观看 | 成年人电影免费在线观看 | 亚州中文av | 免费在线电影网址大全 | 国产午夜麻豆影院在线观看 | 182午夜在线观看 | 8090yy亚洲精品久久 | 欧美日韩国产伦理 | 久久久伦理 | 国产亚洲在线视频 | 亚洲精品小区久久久久久 | 91天堂素人约啪 | 国产精品综合久久久久 | 午夜久久久久久久 | 尤物九九久久国产精品的分类 | 亚洲 综合 国产 精品 | 91在线porny国产在线看 | 九九日九九操 | 国产在线视频资源 | 欧美日韩国产在线一区 | 五月天狠狠操 | 日本韩国精品一区二区在线观看 | 日日麻批40分钟视频免费观看 | 久久综合九色综合久久久精品综合 | 国产人在线成免费视频 | 美女免费视频观看网站 | 中文字幕乱在线伦视频中文字幕乱码在线 | 久久精品亚洲综合专区 | 成年人视频在线免费 | 一区二区三区免费在线观看视频 | 超碰97免费 | 久久精品之 | 国产精品视频永久免费播放 | 在线观看日韩视频 | 亚洲精品大全 | 天天色天天爱天天射综合 | 亚洲国产成人在线 | 亚洲欧美怡红院 | 亚州激情视频 | 久久九九久久 | 日韩欧美视频二区 | 亚洲va欧美va人人爽 | 久久理论影院 | 奇人奇案qvod | 久久好看 | 久久精品欧美一区二区三区麻豆 | 人人爽夜夜爽 | 91久久久久久久 | 日韩免费福利 | 天天爽天天做 | www国产亚洲 | 色资源网在线观看 | 天天干天天操天天搞 | 最新国产在线视频 | 日夜夜精品视频 | 人人爽爽人人 | 91精品网站| 欧美日韩精品区 | 91资源在线播放 | 最近中文字幕大全中文字幕免费 | 99精品视频在线播放观看 | 成年人黄色在线观看 | 欧美日韩国产精品一区二区亚洲 | 欧美在线aaa | 色偷偷88欧美精品久久久 | 美女网站在线免费观看 | 国产精品国产三级国产aⅴ9色 | 国产日韩精品久久 | 日韩xxxx视频 | 国产精品久久久久久久久久直播 | 500部大龄熟乱视频 欧美日本三级 | 天天做天天看 | 91成人观看 | 五月视频 | 久久久96| 亚洲国产一区在线观看 | 精品一区三区 | 99久久久久久 | 中字幕视频在线永久在线观看免费 | 久久在线电影 | 丁香婷婷在线 | 午夜精品麻豆 | 国产精品97 | 亚洲精品在线一区二区三区 | 成人 亚洲 欧美 | 中文字幕在线观看一区 | 奇米影视在线99精品 | 国产丝袜美腿在线 | 在线观看精品一区 | 波多野结衣在线中文字幕 | 曰本三级在线 | 99999精品视频 | 日韩一区精品 | 911av视频| av高清在线 | 久久伊99综合婷婷久久伊 | 在线91色 | 91日韩免费 | 成人免费在线电影 | 精品国产一区二区三区免费 | 国语精品久久 | 欧美精品二区 | 国产精品成人一区二区三区 | 91精品一区在线观看 | 成年人免费在线观看 | 96视频免费在线观看 | 99电影456麻豆 | 国产精品麻 | 国产成人福利在线观看 | 久久草在线免费 | 亚洲乱码在线观看 | 国产日韩在线一区 | 亚洲 中文字幕av | 国产99免费视频 | 婷婷在线综合 | 成人黄色大片网站 | www.天天干.com| 日韩福利在线观看 | 一级片免费在线 | 欧美 日韩 国产 成人 在线 | 天天射天天射天天射 | 99久久成人 | 久草免费在线观看 | 久99久视频 | 91九色自拍| 亚洲激情 欧美激情 | 亚洲午夜久久久影院 | 国产看片 色 | 久久免费看 | 日日夜夜免费精品 | 国产精品久久一区二区三区不卡 | 久久精品波多野结衣 | 亚洲国产日本 | 亚洲天堂自拍视频 | 亚洲精品欧美视频 | 四虎免费在线观看 | 国产资源精品在线观看 | 99久久精品免费看国产四区 | 国产精品网站一区二区三区 | 亚州中文av| 在线观看免费 | 中文字幕在线日本 | 免费福利视频导航 | 中文字幕国产精品 | 亚洲国产免费看 | 久久国产精品一区二区三区 | 操处女逼 | 骄小bbw搡bbbb揉bbbb | 在线观看爱爱视频 | 在线有码中文 | 韩日精品中文字幕 | 精产嫩模国品一二三区 | 在线99视频| 99视频黄 | 亚洲 欧美 国产 va在线影院 | 97操碰 | japanesexxxhd奶水 国产一区二区在线免费观看 | 日韩精品一区二区三区免费观看 | 免费91在线| 久久精品永久免费 | 亚洲精品国产精品国自产观看浪潮 | 国内精品久久久久影院优 | 天天干,天天射,天天操,天天摸 | 久久久久久久久毛片精品 | 手机av在线免费观看 | 91成人免费看片 | 欧美精品首页 | 国产精品 久久 | 色五丁香 | 玖玖视频网 | 日韩欧美在线第一页 | 日韩av一区二区三区四区 | 久久亚洲私人国产精品 | 99这里只有精品99 | 亚洲国产日韩在线 | 日本中文字幕高清 | 黄视频网站大全 | 日韩av一区二区在线 | 久久午夜精品影院一区 | 人人爱爱 | 国产精品综合久久久久 | 91精品国产自产91精品 | 中文在线中文a | av日韩在线网站 | 伊色综合久久之综合久久 | 天天人人| 国产精品美乳一区二区免费 | 国产天天爽 | 成人午夜影视 | 亚洲天堂网在线观看视频 | 色婷婷狠狠干 | 亚洲在线国产 | 日韩视频一区二区 | 国产一区二区精品久久 | 激情丁香综合五月 | 中文字幕色婷婷在线视频 | 欧美日韩午夜 | 日本黄色免费看 | 久久视了 | 91资源在线 | 天天天干天天射天天天操 | 国产精品 日韩精品 | 久久er99热精品一区二区 | 成年人视频免费在线播放 | 久草在线一免费新视频 | 国产资源在线视频 | 五月天伊人| 日本精品视频在线观看 | 国产系列 在线观看 | 久久精品国产第一区二区三区 | 视频一区二区三区视频 | 国产一区不卡在线 | 国产色网 | 五月天欧美精品 | 99一级片 | 91av视频免费观看 | 久草视频手机在线 | 亚洲精品麻豆 | av一级久久 | 99精品久久久久久久久久综合 | 日韩免费不卡av | 国产精品大片免费观看 | 91精品伦理| 91视视频在线直接观看在线看网页在线看 | 久久999久久 | 成人午夜电影在线播放 | 欧美日韩国产高清视频 | 亚洲精品视频在线观看视频 | 99麻豆久久久国产精品免费 | 国产麻豆果冻传媒在线观看 | 国产理论片在线观看 | 狠狠色噜噜狠狠狠 | 久草资源在线观看 | 9992tv成人免费看片 | 午夜丁香网| 奇人奇案qvod | 国产一区二区在线免费 | 碰超在线观看 | 国产黄色精品视频 | 国产欧美久久久精品影院 | 激情欧美xxxx| 色狠狠综合天天综合综合 | 91视频成人免费 | 在线免费观看的av | 亚洲综合在线播放 | 麻豆精品在线 | 五月开心婷婷 | 日韩免费成人 | 91视频成人免费 | 手机在线观看国产精品 | 久久日本视频 | 欧美地下肉体性派对 | 97视频在线观看播放 | 亚洲精品小视频在线观看 | 婷婷激情久久 | 五月天婷婷免费视频 | 欧美成人黄色片 | 成人国产精品入口 | 91传媒在线观看 | av电影在线观看完整版一区二区 | 国产一区二区久久精品 | 国产小视频你懂的在线 | 免费看的av片 | 久久高清| 欧美成人69av | 亚洲成人av免费 | 国产在线不卡视频 | 天天翘av| 日韩三级免费观看 | 最近中文字幕完整高清 | 啪啪肉肉污av国网站 | 亚洲视频电影在线 | a在线免费 | 久久人人爽人人片av | 在线av资源 | 国产精品理论视频 | 亚洲国产黄色 | 精品网站999www | 91精品久久久久久综合乱菊 | 久久久电影网站 | 2020天天干夜夜爽 | 久久夜色网 | 人人插人人 | 91视频午夜 | 久久99九九99精品 | 最近日韩中文字幕中文 | 欧美人操人 | 久久高清av | 久久全国免费视频 | 亚洲精品黄色在线观看 | 亚洲狠狠操 | 依人成人综合网 | 欧美国产三区 | 蜜臀av在线一区二区三区 | 国内精品久久久久久久影视麻豆 | 亚洲天堂网视频在线观看 | 精品 一区 在线 | 午夜精品电影 | 欧美日韩免费网站 | 99久久久国产精品 | 97在线免费视频 | 欧洲色吧| 婷婷在线免费 | 91中文字幕视频 | 黄污在线观看 | 高清色免费 | 91久久国产精品 | 亚洲日本色 | 精品福利网站 | 91一区一区三区 | 亚洲精品欧洲精品 | 91传媒免费在线观看 | 岛国片在线 | 日韩无在线 | 免费av网站在线看 | 国产91精品看黄网站 | 国产视频资源在线观看 | 日韩精品在线视频免费观看 | 免费男女羞羞的视频网站中文字幕 | 久久视频这里有精品 | 天堂网中文在线 | a久久久久久 | 久久精品国产v日韩v亚洲 | 国产一级免费在线观看 | av在线等| 探花视频免费在线观看 | 四虎影视成人永久免费观看亚洲欧美 | 九九欧美视频 | 91chinesexxx| 国产一区二区精品久久 | 久久精品男人的天堂 | 国产美女久久 | 日韩精品一区二区在线 | 国产小视频免费观看 | 久久久久久久国产精品 | 深夜免费福利 | 久草精品在线播放 | 欧美日韩视频在线观看免费 | 日韩av电影手机在线观看 | 国产精品精品国产婷婷这里av | 免费三及片 | 在线视频久 | 视频在线日韩 | 亚洲影视资源 | 天天操天天色天天射 | 久久久久国产一区二区三区 | 久久a v电影| 99热这里有 | 国产一二区免费视频 | 国产精品成久久久久三级 | 日本精品久久久久中文字幕 | 一级黄色大片在线观看 | 久久久高清免费视频 | 狠狠色噜噜狠狠狠狠2022 | 521色香蕉网站在线观看 | 一区二区三区日韩视频在线观看 | 亚洲国产精品99久久久久久久久 | 成人在线观看影院 | 在线观看亚洲专区 | 超碰人人91 | 美女视频a美女大全免费下载蜜臀 | 国产免费叼嘿网站免费 | 激情五月色播五月 | 蜜臀av夜夜澡人人爽人人 | 国产高清专区 | 亚洲视频在线观看免费 | 999视频在线观看 | 99精品在线看 | 91视频高清 | 国产香蕉久久 | 久久免费视频4 | 在线观看网站av | 国产精品美女 | 美女视频久久黄 | 99色资源 | 国产午夜一区 | 一区二区三区在线免费 | 欧产日产国产69 | 一区二区网 | 麻豆视频在线免费看 | 91mv.cool在线观看 | 日本精品久久久久久 | 婷婷九月丁香 | aav在线 | 国产99久久久国产精品 | 国产成人三级三级三级97 | 国产精品自在线 | 日本精品一区二区 | 亚洲国产精品成人综合 | 蜜臀av夜夜澡人人爽人人桃色 | 欧美在线观看视频一区二区 | 在线av资源 | 国产精品久久9 | 午夜精品久久久久久久久久久久 | 国产精品毛片久久久久久久久久99999999 | 久久久久久久国产精品视频 | 中文字幕日韩高清 | 欧美日韩在线视频一区 | 九色精品免费永久在线 | 精品在线观看视频 | 国产日韩欧美在线看 | 天天天射 | 日韩视频a | 99国产在线视频 | 亚洲作爱| 色婷婷丁香 | 一级欧美一级日韩 | 就要干b| 日韩免费一级a毛片在线播放一级 | 亚洲天天在线 | 欧美综合久久久 | 国产第一页福利影院 | 日本精品视频一区二区 | 久久草在线免费 | 91在线小视频| 黄色免费视频在线观看 | av一区二区三区在线 | 就要干b| 97国产精品亚洲精品 | 中文字幕一区二区三区四区久久 | 国产福利91精品一区 | a视频免费 | 91九色蝌蚪视频在线 | 午夜精品久久 | 97超碰在线资源 | 欧美日韩在线视频一区 | 91精品国产自产在线观看永久 | 亚洲激情网站免费观看 | 国产亚洲视频在线观看 | 国产成人久久av977小说 | 国产高清成人在线 | 日韩电影在线观看一区二区 | 99久e精品热线免费 99国产精品久久久久久久久久 | 日韩欧美一区二区在线 | 免费91麻豆精品国产自产在线观看 | 亚洲欧美日韩一区二区三区在线观看 | 黄色亚洲大片免费在线观看 | 免费男女羞羞的视频网站中文字幕 | 婷婷精品国产欧美精品亚洲人人爽 | 在线视频 国产 日韩 | 99久久99视频只有精品 | 黄色毛片视频免费观看中文 | 精品久久中文 | 婷婷亚洲五月 | 欧美成人xxxx| 国产三级国产精品国产专区50 | 免费a网址 | 亚洲在线视频观看 | 亚洲第一中文字幕 | 国产最新在线 | 狠狠狠色丁香综合久久天下网 | 日韩欧美视频一区 | 婷婷激情五月 | a特级毛片 | 免费久久99精品国产婷婷六月 | 日韩欧美一级二级 | 国产精品综合久久久久 | 日韩网站在线播放 | 园产精品久久久久久久7电影 | 亚洲 欧美 变态 国产 另类 | 久草在线视频在线 | 国产日韩欧美在线观看视频 | av黄色亚洲 | 91精品视频免费观看 | 精品国产成人av在线免 | 国产精品日韩精品 | 91一区啪爱嗯打偷拍欧美 | 狠狠狠的干 | 亚洲精品 在线视频 | 毛片区 | 狠狠干综合 | 91精品国产91久久久久福利 | 欧美综合色| 亚洲精品免费在线观看视频 | 国产精品久久网站 | 丁香午夜婷婷 | 香蕉视频免费在线播放 | 在线看国产 | 91精品国产乱码 | 亚洲精品福利在线 | 国产精品女 | 亚洲久草视频 | 国产精品大片 | www.黄色小说.com | 成人黄色电影在线 | 天堂av影院 | 久久免费视频在线观看30 | 高清国产午夜精品久久久久久 | 97超碰伊人 | 91av短视频 | 96亚洲精品久久久蜜桃 | 亚洲综合五月 | 国产色婷婷精品综合在线手机播放 | 极品嫩模被强到高潮呻吟91 | 成年人免费电影 | 91麻豆精品国产91久久久无需广告 | 日韩免费一区 | 欧美精品亚洲精品日韩精品 | 97国产电影 | 狠狠干狠狠久久 | 国产精品1024 | 探花视频免费观看 | 美女中文字幕 | 亚洲欧美在线观看视频 | 日韩欧美一区二区在线观看 | 狠狠色丁香婷婷综合久久片 | 欧美成人性战久久 | 西西人体4444www高清视频 | 久久精品视频免费播放 | 欧美精品中文字幕亚洲专区 | 精品女同一区二区三区在线观看 | 久久综合五月天婷婷伊人 | 色五月色开心色婷婷色丁香 | 中文字幕区| 精品国产电影一区二区 | 免费视频久久 | 久久久精品久久日韩一区综合 | 日本公妇在线观看 | 国产精品四虎 | 日韩av在线网站 | 久草99 | 毛片网站在线看 | 97视频免费观看 | 国产九九九九九 | 激情欧美一区二区免费视频 | 日韩高清在线一区二区 | www·22com天天操| 亚洲女同ⅹxx女同tv | 午夜精品久久久 | 99精品国产一区二区三区不卡 | 亚洲第一区精品 | 久久精品久久99精品久久 | 日本一区二区三区免费观看 | 夜夜躁日日躁 | 久草在线高清视频 | 久久久国产日韩 | 国产美女视频免费观看的网站 | 在线 国产 亚洲 欧美 | 日韩免费视频一区二区 | 午夜精品一区二区三区在线 | 中文字幕资源在线 | 日韩高清在线一区 | 中文字幕亚洲欧美日韩2019 | 九九九九色 | 国产精品国产精品 | 天天操夜夜操夜夜操 | 激情综合狠狠 | 精品在线一区二区三区 | 中文字幕在线免费97 | 99re久久资源最新地址 | 粉嫩av一区二区三区四区在线观看 | av网站地址| 欧美一级欧美一级 | japanesexxxhd奶水 国产一区二区在线免费观看 | 在线a人v观看视频 | 中文字幕高清 | 在线亚洲精品 | 天天操天天操一操 | 天天操天天色天天 | 午夜性生活片 | 成人app在线播放 | 精品美女在线视频 | 天天干天天干天天操 | 五月婷婷狠狠 | 黄色av电影在线 | 久久久穴 | 免费久草视频 | 日韩视频精品在线 | 在线黄色观看 | 精品美女在线视频 | 久久se视频 | 久久人人插 | 国产精品美女毛片真酒店 | 国产一级精品绿帽视频 | 欧美日韩国产精品一区 | 精品国产乱码久久久久久1区2匹 | 日韩在线视频网 | 亚洲国产日韩一区 | 国产麻豆视频免费观看 | 人人干狠狠操 | 婷婷丁香视频 | 99精品国产99久久久久久福利 | 国产91精品一区二区麻豆网站 | 麻豆免费视频网站 | 亚洲国产日本 | 日日躁夜夜躁xxxxaaaa | 91看片一区二区三区 | 蜜臀av性久久久久av蜜臀三区 | 91精品国产91久久久久久三级 | 日韩欧美久久 | 黄色在线视频网址 | 91完整版 | 日韩一区二区在线免费观看 | 精品一区二区三区香蕉蜜桃 | 极品久久久久 | 2020天天干夜夜爽 | 波多野结衣在线播放视频 | 国产成人精品在线观看 | 天天干天天上 | 日韩在线观看你懂的 | 日韩色爱| 国产精品成人一区二区 | 小草av在线播放 | 日韩在线一二三区 | 手机在线永久免费观看av片 | 午夜视频在线观看一区二区三区 | 亚洲成a人片在线www | 日韩在线视频精品 | 黄色成年 | 18国产精品白浆在线观看免费 | 欧洲一区二区三区精品 | 欧美日韩在线电影 | 亚洲一级免费观看 | 最新一区二区三区 | 狠狠干成人综合网 | 亚洲jizzjizz日本少妇 | 欧美美女视频在线观看 | 日韩一区二区三区免费视频 | 欧美在线你懂的 | 免费在线观看国产精品 | 久草视频在 | 日本久久视频 | 久久久久视 | 亚洲午夜精品一区二区三区电影院 | 国产精品免费久久久 | 91视频这里只有精品 | 欧美 日韩精品 | 天天草天天爽 | 精品国内自产拍在线观看视频 | 国产一级91 | 久久久91精品国产一区二区精品 | 亚洲精品国产精品乱码在线观看 | 六月激情网 | 精品国产电影一区二区 | 成人免费观看视频网站 | 久久天天躁狠狠躁亚洲综合公司 | 在线观看你懂的网站 | 亚洲激情视频 | 四虎国产精品成人免费4hu | 欧美日本一二三 | 成年人网站免费在线观看 | 伊人激情综合 | 91亚洲精品久久久 | 三级黄在线 | 啪啪动态视频 | 久久久免费精品视频 | 最近中文字幕免费 | 国产精品免费av | 成人影音av| 很黄很污的视频网站 | 丁香亚洲 | av丁香花| 久久久久网址 | 天天操综 | 91av播放 | 久久中文字幕在线视频 | 国产精品嫩草影视久久久 | 欧美精品久久久久久久久久 | 久久人人爽视频 | 特级西西人体444是什么意思 | 在线观看免费福利 | 亚洲精品中文字幕视频 | 91尤物在线播放 | 波多野结衣电影一区二区三区 | 九九热久久免费视频 | av丝袜天堂 | 91麻豆精品国产91久久久久久 | 91黄色小网站 | 久久久久久久久久久久电影 | 亚洲国产成人久久综合 | 亚洲精品乱码久久久久v最新版 | 91高清免费 | av色综合网 | 婷婷色六月天 | 91中文字幕永久在线 | 欧美一级性生活视频 | 日日干激情五月 | 免费日韩一区二区三区 | 国产精品久久久久久一区二区三区 | 国产麻豆电影在线观看 | 奇米网8888| 欧美三人交 | 日韩久久精品一区二区三区 |