一、前言
其實(shí)爬取頁(yè)面的思路都差不多,觀察爬取頁(yè)面源碼,獲取頁(yè)面內(nèi)容,根據(jù)源碼的格式規(guī)律將自己需要的內(nèi)容提取出來(lái),提取后美化輸出或者保存!
之前寫(xiě)過(guò)了如何爬取淘寶和京東的評(píng)論,其實(shí)這個(gè)可以不寫(xiě)的?。〉怯钟龅娇恿怂赃€是寫(xiě)下來(lái),記錄一下錯(cuò)誤?。?/p>
二、代碼與問(wèn)題
先上代碼再說(shuō)一下自己遇到的問(wèn)題!
# -*- coding:utf-8 -*-
import requests
from requests.exceptions import RequestException
import re
import json
import time
from multiprocessing import Pool
"""
url= 'https://maoyan.com/board/4'
repsponse = requests.get(url)
print(repsponse.headers['content-type'])
print(repsponse.encoding)#response內(nèi)容的編碼
print(repsponse.apparent_encoding)#response headers里設(shè)置的編碼
print(requests.utils.get_encodings_from_content(repsponse.text))#response返回的html header標(biāo)簽里設(shè)置的編碼
"""
def get_url(url):
try:
#說(shuō)明headers信息,不然一下就403錯(cuò)誤了!
heards = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
#獲取頁(yè)面信息
response = requests.get(url,headers=heards)
#頁(yè)面返回的status_code碼為200則是爬取成功
if response.status_code == 200:
#聲明頁(yè)面返回內(nèi)容的編碼格式,不然一般是ISO-8859-1,就亂碼了
response.encoding = 'utf-8'
return response.text
return print("爬取失敗")
except RequestException:
return print("爬取失敗")
def parge_html(html):
#編寫(xiě)正則表達(dá)式的格式
#compile() 函數(shù)將一個(gè)字符串編譯為字節(jié)代碼
pattern = re.compile('<dd>.*?board-index.*?(\d+).*?name.*?<a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">'
+'(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(\d+)</i>.*?</dd>',re.S)
#利用正則表達(dá)式獲取需要的內(nèi)容
items = re.findall(pattern,html)
#print(items)
#將內(nèi)容轉(zhuǎn)化為一個(gè)字典使其更容易觀看
for item in items:
yield{
'index':item[0],
'name':item[1],
'star':item[2].strip()[3:], #strip() 方法用于移除字符串頭尾指定的字符(默認(rèn)為空格或換行符)或字符序列。
'time':item[3][5:],
'score':item[4]+item[5]
}
def write_to_file(content):
with open('result1.txt', 'a', encoding='utf-8') as f:
#ensure_ascii=False,說(shuō)明輸出的內(nèi)容不要用ASCII編碼,這樣結(jié)果才是中文
f.write(json.dumps(content,ensure_ascii=False) + '\n') #利用json.dumps將字典轉(zhuǎn)為字符串
f.close()
def main(offset):
#切換頁(yè)面觀察URL的變化
url = 'https://maoyan.com/board/4?offset=' + str(offset)
html = get_url(url)
for item in parge_html(html):
print(item)
write_to_file(item)
#print(html)
if __name__ == "__main__":
#單線程爬取
"""
for i in range(10):
time.sleep(10)
main(i*10)
"""
#多線程
pool = Pool(processes = 10) #默認(rèn)的話進(jìn)程數(shù)為cpu_count()的值
pool.map(main,[i*10 for i in range(10)])
問(wèn)題1:
我最開(kāi)始寫(xiě)的是爬取一頁(yè)的電影內(nèi)容,沒(méi)有用正則表達(dá)式轉(zhuǎn)化提取,但是輸出的內(nèi)容是亂碼的!
既然亂碼就是編碼問(wèn)題了,由于我是已經(jīng)聲明utf-8的編碼模式了,我以為是軟件問(wèn)題,我是用pycharm(第一次用我也不知道它初始編碼是什么,之前一直用Spyder),我查了一下怎么修改pycharm的編碼,file—>settings—>Editor—>File Encoding,一看那里有一個(gè)是gbk,我就都改為了utf-8!

但是重新輸出后還是亂碼??!
在網(wǎng)上找了好久,終于看到有一篇說(shuō)到點(diǎn)了,其他大部分要么教我修改pycharm編碼要么在程序一開(kāi)始聲明utf-8但是都沒(méi)用!
原來(lái)是因?yàn)樵谀阏{(diào)用Response.text時(shí)對(duì)響應(yīng)進(jìn)行解碼,如果http頭部有聲明則基本上按聲明進(jìn)行解碼,沒(méi)用它就會(huì)猜!使用默認(rèn)的 ISO-8859-1解碼,有時(shí)http頭部聲明了也還是按照這個(gè)解碼!
print(repsponse.encoding)#response內(nèi)容的編碼
print(repsponse.apparent_encoding)#response headers里設(shè)置的編碼
print(requests.utils.get_encodings_from_content(repsponse.text))#response返回的html header標(biāo)簽里設(shè)置的編碼
可以輸入上面的代碼看一下是不是編碼出問(wèn)題,我的輸出是:ISO-8859-1,utf-8,utf-8請(qǐng)求返回的內(nèi)容變成了ISO-8859-1肯定亂碼!
可以在獲取內(nèi)容后先輸入:
response.encoding = 'utf-8'
聲明請(qǐng)求返回內(nèi)容是utf-8編碼。
問(wèn)題2:
問(wèn)題1解決后我又爬了一次!這次沒(méi)有亂碼,但是因?yàn)槲以谡{(diào)整編碼的時(shí)候一直測(cè)試一直爬,貓眼覺(jué)得我的請(qǐng)求很可疑!禁止了我的請(qǐng)求,出現(xiàn)了403錯(cuò)誤!
這個(gè)通過(guò)增加一個(gè)頭部信息就好了,之前淘寶比較嚴(yán)格,頭部信息比較多。這次就加了一個(gè)請(qǐng)求的瀏覽器類(lèi)型就可以了!
問(wèn)題3:
問(wèn)題2解決后,我接著完善,剛剛是爬取一頁(yè),現(xiàn)在是十頁(yè)!但是又出問(wèn)題了爬的太頻繁太快被要求驗(yàn)證身份了,也就是類(lèi)似拼圖,但是我爬取的內(nèi)容還沒(méi)完呢!少了一頁(yè),所以我又加了睡眠信息,每十秒爬一次,終于成功了!這是單線程!
接下來(lái)是多線程爬?。憾嗑€程一般默認(rèn)是cpu_count()數(shù),我的是8,但是我自己定義開(kāi)了十個(gè)進(jìn)程。
天下武功唯快不破?。。∮昧耸畟€(gè)進(jìn)程秒爬,估計(jì)貓眼沒(méi)反應(yīng)過(guò)來(lái),最后爬取內(nèi)容缺了一個(gè)而已!
但是多線程有一個(gè)缺點(diǎn),就是爬取的內(nèi)容不是按順序的,本來(lái)是top100的電影從1-100,多線程的話內(nèi)容有點(diǎn)亂!但是問(wèn)題不大,因?yàn)樗芸炀秃昧恕?/p>
參考:https://www.bilibili.com/video/BV1Si4y1s7S4?p=14
https://www.runoob.com/python/python-func-compile.html
https://www.runoob.com/python/att-string-strip.html
https://www.cnblogs.com/biangbiang/archive/2013/02/19/2916780.html
https://blog.csdn.net/a491057947/article/details/47292923
https://blog.csdn.net/weixin_43877278/article/details/103880644