Returns an iterator of dictionaries from the given csv object obj can be: - a Response object - a unicode string - a string encoded as utf-8 delimiter is the character used to separate fields on the given obj. headers is an iterable that when provided offers the keys f
(
obj: Response | str | bytes,
delimiter: str | None = None,
headers: list[str] | None = None,
encoding: str | None = None,
quotechar: str | None = None,
)
| 156 | |
| 157 | |
| 158 | def csviter( |
| 159 | obj: Response | str | bytes, |
| 160 | delimiter: str | None = None, |
| 161 | headers: list[str] | None = None, |
| 162 | encoding: str | None = None, |
| 163 | quotechar: str | None = None, |
| 164 | ) -> Iterator[dict[str, str]]: |
| 165 | """Returns an iterator of dictionaries from the given csv object |
| 166 | |
| 167 | obj can be: |
| 168 | - a Response object |
| 169 | - a unicode string |
| 170 | - a string encoded as utf-8 |
| 171 | |
| 172 | delimiter is the character used to separate fields on the given obj. |
| 173 | |
| 174 | headers is an iterable that when provided offers the keys |
| 175 | for the returned dictionaries, if not the first row is used. |
| 176 | |
| 177 | quotechar is the character used to enclosure fields on the given obj. |
| 178 | """ |
| 179 | |
| 180 | if encoding is not None: # pragma: no cover |
| 181 | warn( |
| 182 | "The encoding argument of csviter() is ignored and will be removed" |
| 183 | " in a future Scrapy version.", |
| 184 | category=ScrapyDeprecationWarning, |
| 185 | stacklevel=2, |
| 186 | ) |
| 187 | |
| 188 | lines = StringIO(_body_or_str(obj, unicode=True)) |
| 189 | |
| 190 | kwargs: dict[str, Any] = {} |
| 191 | if delimiter: |
| 192 | kwargs["delimiter"] = delimiter |
| 193 | if quotechar: |
| 194 | kwargs["quotechar"] = quotechar |
| 195 | csv_r = csv.reader(lines, **kwargs) |
| 196 | |
| 197 | if not headers: |
| 198 | try: |
| 199 | headers = next(csv_r) |
| 200 | except StopIteration: |
| 201 | return |
| 202 | |
| 203 | for row in csv_r: |
| 204 | if len(row) != len(headers): |
| 205 | logger.warning( |
| 206 | "ignoring row %(csvlnum)d (length: %(csvrow)d, " |
| 207 | "should be: %(csvheader)d)", |
| 208 | { |
| 209 | "csvlnum": csv_r.line_num, |
| 210 | "csvrow": len(row), |
| 211 | "csvheader": len(headers), |
| 212 | }, |
| 213 | ) |
| 214 | continue |
| 215 | yield dict(zip(headers, row, strict=False)) |