记一次爬虫

记一次基本的爬虫。

爬取淘宝搜索某商品出现的信息

因为淘宝现在要登录才能进行商品搜索,所以我们先在网页上进行登录,然后获取相关的header与cookie,最后利用参数来登录请求相关页面。

1、登录淘宝

2、随便搜索某一商品,打开网络资源,刷新一下找到search

image-20220308185109876

3、右键,复制为cURL

image-20220308185221096

4、在 https://curlconverter.com/ 将上一步复制的curl访问命令转化为python的请求方式。

image-20220308185444267

5、复制出上一步转化得到的python请求代码,补充好相关请求和解析数据的代码即可。

完整代码:url中的s参数表示正在访问的页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#coding=GBK
import requests
import re
import csv

def get_html():
name = "休闲养生食品"
start_url = 'https://s.taobao.com/search?q={}&s='.format(name)
header = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0'
}

cookies = {''} #登录后从网络资源中获取

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Cache-Control': 'max-age=0',
}

pages = 100
goods = ''
for i in range(int(pages)):
url = start_url + str(i*44)
print(url)
r = requests.get(url, headers=headers, cookies=cookies, timeout=60)
assert r.status_code == 200
r.encoding = r.apparent_encoding
goods += r.text
#print(r.text)
print("爬取进度: %d%%"%(((i+1)/pages)*100))
#exit()
#print(goods)
return goods

def find_ms(html):
titles = re.findall('"raw_title":"(.*?)"', html)
pays = re.findall('"view_sales":"(.*?)人付款"', html)
pays = [i.replace('+', '') for i in pays]
pays = [i.replace('万', '0000') if i.find('万') != -1 else i for i in pays]
#print(pays)
data = []
for i in range(len(titles)):
data.append([titles[i], pays[i]])
#print(data)
return data

def save_file(data):
path = 'data_taobao.csv'
f = open(path, "w", newline="")
writer = csv.writer(f)
writer.writerow(['商品', '付款人数'])
writer.writerows(data)
f.close()

goods = get_html()
data = find_ms(goods)
save_file(data)

爬取知乎中搜索某话题的综合相关内容

如搜索朋克养生,要爬取的页面如下:

image-20220308190349236

因为是第一次接触爬虫,以为简单的把页面数据请求下来使用正则匹配需要的内容就好了,但发现请求的内容根本没有页面展示出的相关内容,只有一个框架。

经过相关了解后,发现这是一个使用ajax异步加载的页面,也就是说我们需要的数据是在访问页面过程中动态加载的,我们在脚本中请求只能获得静态页面(由于requests模块是一个不完全模拟浏览器行为的模块,只能爬取到网页的HTML文档信息,无法解析和执行CSS、JavaScript代码),接着我从网络资源中的xhr页面中找到真正获取数据的接口:

image-20220308191152611

image-20220308191259657

但是直接请求这个接口服务端并不会正确返回,因为有相关字段(x-zse-93,x-zse-96,x-zse-81)进行校验,这也简单,其中x-zse-93与x-zse-81是固定的,我们只需要从js代码中逆向出x-zse-96的计算方法,爬取页面的时候模拟计算一下就好。而弄完,又遇到了其它的问题,访问接口的search_hash_id不止一种,这就使x-zse-96字段的值也不止一种,且相关处理也挺麻烦的,因此我使用了另外一种爬取方法:使用selenium接管本地打开的浏览器然后利用执行js代码对页面滚动条进行滑动,最后获取匹配我们需要的关键信息。(知乎对selenium进行了反爬处理,即对相关字符串进行了检查)

1、本地以一个端口启动chorm

1
chrome.exe --remote-debugging-port=9222 --user-data-dir="./"

2、使用selenium接管上一步打开的浏览器,访问要爬取页面的url

3、利用执行js代码的方式不断向下滑动滚动条加载数据,不断加大滚动条与顶部的距离

image-20220308194129986

4、利用相关标签匹配所需要的数据并进行正则匹配

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#coding=gbk
import selenium.webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
import re
import csv

def match_data(driver, xpath, data):
for content in driver.find_elements(by=By.XPATH, value=xpath):
tmp = []
tmp += [content.find_element(by=By.CLASS_NAME, value="Highlight").text]
ans = list(re.findall("赞同.?(.*?)\n([0-9]*).*\n(.*)", content.find_element(by=By.CLASS_NAME, value="ContentItem-actions").text)[0])
tmp += ['0' if i == '' else i for i in ans]
data += [tmp]

def get_data(data):
name = "朋克养生"
url = 'https://www.zhihu.com/search?q={}&utm_content=search_history&type=content'.format(name)
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = selenium.webdriver.Chrome(options=chrome_options)
driver.get(url)
for i in range(100):
js = 'var action=document.documentElement.scrollTop={}'.format(1000+300*i)
driver.execute_script(js)
print("爬取进度: %d%%"%(((1000+300*i)/(1000+300*99))*100))
time.sleep(1)
match_data(driver, "//div[@class='ContentItem AnswerItem']", data)
match_data(driver, "//div[@class='ContentItem ArticleItem']", data)

def save_file(data):
path = 'data_zhihu.csv'
f = open(path, "w", newline="")
writer = csv.writer(f)
writer.writerow(['问题', '点赞数', '评论数', '日期'])
writer.writerows(data)
f.close()

if __name__ == '__main__':
data = []
get_data(data)
article_num = len(data)
voteup_sum = sum([int(i[1].replace(' 万', '0000')) if '万' in i[1] else int(i[1]) for i in data])
comment_sum = sum([int(i[2]) for i in data])
print("爬取完成,文章总数: %d, 点赞总数: %d, 评论总数: %d"%(article_num, voteup_sum, comment_sum))
save_file(data)
-------------本文结束感谢您的阅读-------------